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
33 #include "avifile_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
39 /***********************************************************************/
41 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,REFIID refiid
,LPVOID
*obj
);
42 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
);
43 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
);
44 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
,LPARAM lParam1
,LPARAM lParam2
);
45 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,AVISTREAMINFOW
*psi
,LONG size
);
46 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
,LONG pos
,LONG flags
);
47 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
,LONG pos
,LPVOID format
,LONG
*formatsize
);
48 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
,LONG pos
,LPVOID format
,LONG formatsize
);
49 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
,LONG start
,LONG samples
,LPVOID buffer
,LONG buffersize
,LONG
*bytesread
,LONG
*samplesread
);
50 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
,LONG start
,LONG samples
,LPVOID buffer
,LONG buffersize
,DWORD flags
,LONG
*sampwritten
,LONG
*byteswritten
);
51 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
,LONG start
,LONG samples
);
52 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
,DWORD fcc
,LPVOID lp
,LONG
*lpread
);
53 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
,DWORD fcc
,LPVOID lp
,LONG size
);
54 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,AVISTREAMINFOW
*info
,LONG infolen
);
56 static const struct IAVIStreamVtbl iacmst
= {
57 ACMStream_fnQueryInterface
,
62 ACMStream_fnFindSample
,
63 ACMStream_fnReadFormat
,
64 ACMStream_fnSetFormat
,
69 ACMStream_fnWriteData
,
73 typedef struct _IAVIStreamImpl
{
75 const IAVIStreamVtbl
*lpVtbl
;
78 /* IAVIStream stuff */
84 LPWAVEFORMATEX lpInFormat
;
87 LPWAVEFORMATEX lpOutFormat
;
90 ACMSTREAMHEADER acmStreamHdr
;
93 /***********************************************************************/
95 #define CONVERT_STREAM_to_THIS(a) do { \
97 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
98 &__bytes, ACM_STREAMSIZEF_SOURCE); \
99 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
101 #define CONVERT_THIS_to_STREAM(a) do { \
103 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
104 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
105 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
107 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
);
109 HRESULT
AVIFILE_CreateACMStream(REFIID riid
, LPVOID
*ppv
)
111 IAVIStreamImpl
*pstream
;
114 assert(riid
!= NULL
&& ppv
!= NULL
);
118 pstream
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAVIStreamImpl
));
120 return AVIERR_MEMORY
;
122 pstream
->lpVtbl
= &iacmst
;
124 hr
= IAVIStream_QueryInterface((IAVIStream
*)pstream
, riid
, ppv
);
126 HeapFree(GetProcessHeap(), 0, pstream
);
131 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,
132 REFIID refiid
, LPVOID
*obj
)
134 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
136 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(refiid
), obj
);
138 if (IsEqualGUID(&IID_IUnknown
, refiid
) ||
139 IsEqualGUID(&IID_IAVIStream
, refiid
)) {
141 IAVIStream_AddRef(iface
);
146 return OLE_E_ENUM_NOMORE
;
149 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
)
151 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
152 ULONG ref
= InterlockedIncrement(&This
->ref
);
154 TRACE("(%p) -> %ld\n", iface
, ref
);
156 /* also add reference to the nested stream */
157 if (This
->pStream
!= NULL
)
158 IAVIStream_AddRef(This
->pStream
);
163 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
)
165 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
166 ULONG ref
= InterlockedDecrement(&This
->ref
);
168 TRACE("(%p) -> %ld\n", iface
, ref
);
172 if (This
->has
!= NULL
) {
173 if (This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
)
174 acmStreamUnprepareHeader(This
->has
, &This
->acmStreamHdr
, 0);
175 acmStreamClose(This
->has
, 0);
178 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
179 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
180 This
->acmStreamHdr
.pbSrc
= NULL
;
182 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
183 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
184 This
->acmStreamHdr
.pbDst
= NULL
;
186 if (This
->lpInFormat
!= NULL
) {
187 HeapFree(GetProcessHeap(), 0, This
->lpInFormat
);
188 This
->lpInFormat
= NULL
;
189 This
->cbInFormat
= 0;
191 if (This
->lpOutFormat
!= NULL
) {
192 HeapFree(GetProcessHeap(), 0, This
->lpOutFormat
);
193 This
->lpOutFormat
= NULL
;
194 This
->cbOutFormat
= 0;
196 if (This
->pStream
!= NULL
) {
197 IAVIStream_Release(This
->pStream
);
198 This
->pStream
= NULL
;
200 HeapFree(GetProcessHeap(), 0, This
);
205 /* also release reference to the nested stream */
206 if (This
->pStream
!= NULL
)
207 IAVIStream_Release(This
->pStream
);
212 /* lParam1: PAVISTREAM
213 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
215 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
, LPARAM lParam1
,
218 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
220 TRACE("(%p,0x%08lX,0x%08lX)\n", iface
, lParam1
, lParam2
);
222 /* check for swapped parameters */
223 if ((LPVOID
)lParam1
!= NULL
&&
224 ((LPAVICOMPRESSOPTIONS
)lParam1
)->fccType
== streamtypeAUDIO
) {
225 register LPARAM tmp
= lParam1
;
231 if ((LPVOID
)lParam1
== NULL
)
232 return AVIERR_BADPARAM
;
234 IAVIStream_Info((PAVISTREAM
)lParam1
, &This
->sInfo
, sizeof(This
->sInfo
));
235 if (This
->sInfo
.fccType
!= streamtypeAUDIO
)
236 return AVIERR_ERROR
; /* error in registry or AVIMakeCompressedStream */
238 This
->sInfo
.fccHandler
= 0; /* be paranoid */
240 /* FIXME: check ACM version? Which version does we need? */
242 if ((LPVOID
)lParam2
!= NULL
) {
243 /* We only need the format from the compress-options */
244 if (((LPAVICOMPRESSOPTIONS
)lParam2
)->fccType
== streamtypeAUDIO
)
245 lParam2
= (LPARAM
)((LPAVICOMPRESSOPTIONS
)lParam2
)->lpFormat
;
247 if (((LPWAVEFORMATEX
)lParam2
)->wFormatTag
!= WAVE_FORMAT_PCM
)
248 This
->cbOutFormat
= sizeof(WAVEFORMATEX
) + ((LPWAVEFORMATEX
)lParam2
)->cbSize
;
250 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
252 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
253 if (This
->lpOutFormat
== NULL
)
254 return AVIERR_MEMORY
;
256 memcpy(This
->lpOutFormat
, (LPVOID
)lParam2
, This
->cbOutFormat
);
258 This
->lpOutFormat
= NULL
;
259 This
->cbOutFormat
= 0;
262 This
->pStream
= (PAVISTREAM
)lParam1
;
263 IAVIStream_AddRef(This
->pStream
);
268 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,LPAVISTREAMINFOW psi
,
271 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
273 TRACE("(%p,%p,%ld)\n", iface
, psi
, size
);
276 return AVIERR_BADPARAM
;
278 return AVIERR_BADSIZE
;
280 /* Need codec to correct some values in structure */
281 if (This
->has
== NULL
) {
282 HRESULT hr
= AVIFILE_OpenCompressor(This
);
288 memcpy(psi
, &This
->sInfo
, min(size
, (LONG
)sizeof(This
->sInfo
)));
290 if (size
< (LONG
)sizeof(This
->sInfo
))
291 return AVIERR_BUFFERTOOSMALL
;
295 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
, LONG pos
,
298 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
300 TRACE("(%p,%ld,0x%08lX)\n",iface
,pos
,flags
);
302 if (flags
& FIND_FROM_START
) {
303 pos
= This
->sInfo
.dwStart
;
304 flags
&= ~(FIND_FROM_START
|FIND_PREV
);
308 /* convert pos from our 'space' to This->pStream's one */
309 CONVERT_THIS_to_STREAM(&pos
);
312 pos
= IAVIStream_FindSample(This
->pStream
, pos
, flags
);
315 /* convert pos back to our 'space' if it's no size or physical pos */
316 if ((flags
& FIND_RET
) == 0)
317 CONVERT_STREAM_to_THIS(&pos
);
323 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
, LONG pos
,
324 LPVOID format
, LONG
*formatsize
)
326 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
328 TRACE("(%p,%ld,%p,%p)\n", iface
, pos
, format
, formatsize
);
330 if (formatsize
== NULL
)
331 return AVIERR_BADPARAM
;
333 if (This
->has
== NULL
) {
334 HRESULT hr
= AVIFILE_OpenCompressor(This
);
340 /* only interested in needed buffersize? */
341 if (format
== NULL
|| *formatsize
<= 0) {
342 *formatsize
= This
->cbOutFormat
;
347 /* copy initial format (only as much as will fit) */
348 memcpy(format
, This
->lpOutFormat
, min(*formatsize
, This
->cbOutFormat
));
349 if (*formatsize
< This
->cbOutFormat
) {
350 *formatsize
= This
->cbOutFormat
;
351 return AVIERR_BUFFERTOOSMALL
;
354 *formatsize
= This
->cbOutFormat
;
358 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
, LONG pos
,
359 LPVOID format
, LONG formatsize
)
361 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
365 TRACE("(%p,%ld,%p,%ld)\n", iface
, pos
, format
, formatsize
);
367 /* check parameters */
368 if (format
== NULL
|| formatsize
<= 0)
369 return AVIERR_BADPARAM
;
371 /* Input format already known?
372 * Changing is unsupported, but be quiet if it's the same */
373 if (This
->lpInFormat
!= NULL
) {
374 if (This
->cbInFormat
!= formatsize
||
375 memcmp(format
, This
->lpInFormat
, formatsize
) != 0)
376 return AVIERR_UNSUPPORTED
;
381 /* Does the nested stream support writing? */
382 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
383 return AVIERR_READONLY
;
385 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, formatsize
);
386 if (This
->lpInFormat
== NULL
)
387 return AVIERR_MEMORY
;
388 This
->cbInFormat
= formatsize
;
389 memcpy(This
->lpInFormat
, format
, formatsize
);
391 /* initialize formats and get compressor */
392 hr
= AVIFILE_OpenCompressor(This
);
396 CONVERT_THIS_to_STREAM(&pos
);
398 /* tell the nested stream the new format */
399 return IAVIStream_SetFormat(This
->pStream
, pos
, This
->lpOutFormat
,
403 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
, LONG start
,
404 LONG samples
, LPVOID buffer
,
405 LONG buffersize
, LPLONG bytesread
,
408 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
413 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", iface
, start
, samples
, buffer
,
414 buffersize
, bytesread
, samplesread
);
416 /* clear return parameters if given */
417 if (bytesread
!= NULL
)
419 if (samplesread
!= NULL
)
422 /* Do we have our compressor? */
423 if (This
->has
== NULL
) {
424 hr
= AVIFILE_OpenCompressor(This
);
430 /* only need to pass through? */
431 if (This
->cbInFormat
== This
->cbOutFormat
&&
432 memcmp(This
->lpInFormat
, This
->lpOutFormat
, This
->cbInFormat
) == 0) {
433 return IAVIStream_Read(This
->pStream
, start
, samples
, buffer
, buffersize
,
434 bytesread
, samplesread
);
437 /* read as much as fit? */
439 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
440 /* limit to buffersize */
441 if (samples
* This
->lpOutFormat
->nBlockAlign
> buffersize
)
442 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
444 /* only return needed size? */
445 if (buffer
== NULL
|| buffersize
<= 0 || samples
== 0) {
446 if (bytesread
== NULL
&& samplesread
== NULL
)
447 return AVIERR_BADPARAM
;
449 if (bytesread
!= NULL
)
450 *bytesread
= samples
* This
->lpOutFormat
->nBlockAlign
;
451 if (samplesread
!= NULL
)
452 *samplesread
= samples
;
457 /* map our positions to pStream positions */
458 CONVERT_THIS_to_STREAM(&start
);
460 /* our needed internal buffersize */
461 size
= samples
* This
->lpInFormat
->nBlockAlign
;
463 /* Need to free destination buffer used for writing? */
464 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
465 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
466 This
->acmStreamHdr
.pbDst
= NULL
;
467 This
->acmStreamHdr
.dwDstUser
= 0;
470 /* need bigger source buffer? */
471 if (This
->acmStreamHdr
.pbSrc
== NULL
||
472 This
->acmStreamHdr
.dwSrcUser
< size
) {
473 if (This
->acmStreamHdr
.pbSrc
== NULL
)
474 This
->acmStreamHdr
.pbSrc
= HeapAlloc(GetProcessHeap(), 0, size
);
476 This
->acmStreamHdr
.pbDst
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
, size
);
477 if (This
->acmStreamHdr
.pbSrc
== NULL
)
478 return AVIERR_MEMORY
;
479 This
->acmStreamHdr
.dwSrcUser
= size
;
482 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
483 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
484 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
485 This
->acmStreamHdr
.cbSrcLength
= size
;
487 /* read source data */
488 hr
= IAVIStream_Read(This
->pStream
, start
, -1, This
->acmStreamHdr
.pbSrc
,
489 This
->acmStreamHdr
.cbSrcLength
,
490 (LONG
*)&This
->acmStreamHdr
.cbSrcLength
, NULL
);
491 if (FAILED(hr
) || This
->acmStreamHdr
.cbSrcLength
== 0)
494 /* need to prepare stream? */
495 This
->acmStreamHdr
.pbDst
= buffer
;
496 This
->acmStreamHdr
.cbDstLength
= buffersize
;
497 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
498 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
499 This
->acmStreamHdr
.pbDst
= NULL
;
500 This
->acmStreamHdr
.cbDstLength
= 0;
501 return AVIERR_COMPRESSOR
;
505 /* now do the conversion */
506 /* FIXME: use ACM_CONVERTF_* flags */
507 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
508 hr
= AVIERR_COMPRESSOR
;
510 This
->acmStreamHdr
.pbDst
= NULL
;
511 This
->acmStreamHdr
.cbDstLength
= 0;
513 /* fill out return parameters if given */
514 if (bytesread
!= NULL
)
515 *bytesread
= This
->acmStreamHdr
.cbDstLengthUsed
;
516 if (samplesread
!= NULL
)
518 This
->acmStreamHdr
.cbDstLengthUsed
/ This
->lpOutFormat
->nBlockAlign
;
523 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
, LONG start
,
524 LONG samples
, LPVOID buffer
,
525 LONG buffersize
, DWORD flags
,
529 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
534 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n", iface
, start
, samples
,
535 buffer
, buffersize
, flags
, sampwritten
, byteswritten
);
537 /* clear return parameters if given */
538 if (sampwritten
!= NULL
)
540 if (byteswritten
!= NULL
)
543 /* check parameters */
544 if (buffer
== NULL
&& (buffersize
> 0 || samples
> 0))
545 return AVIERR_BADPARAM
;
547 /* Have we write capability? */
548 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
549 return AVIERR_READONLY
;
551 /* also need a compressor */
552 if (This
->has
== NULL
)
553 return AVIERR_NOCOMPRESSOR
;
555 /* map our sizes to pStream sizes */
557 CONVERT_THIS_to_STREAM(&size
);
558 CONVERT_THIS_to_STREAM(&start
);
560 /* no bytes to write? -- short circuit */
562 return IAVIStream_Write(This
->pStream
, -1, samples
, buffer
, size
,
563 flags
, sampwritten
, byteswritten
);
566 /* Need to free source buffer used for reading? */
567 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
568 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
569 This
->acmStreamHdr
.pbSrc
= NULL
;
570 This
->acmStreamHdr
.dwSrcUser
= 0;
573 /* Need bigger destination buffer? */
574 if (This
->acmStreamHdr
.pbDst
== NULL
||
575 This
->acmStreamHdr
.dwDstUser
< size
) {
576 if (This
->acmStreamHdr
.pbDst
== NULL
)
577 This
->acmStreamHdr
.pbDst
= HeapAlloc(GetProcessHeap(), 0, size
);
579 This
->acmStreamHdr
.pbDst
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
, size
);
580 if (This
->acmStreamHdr
.pbDst
== NULL
)
581 return AVIERR_MEMORY
;
582 This
->acmStreamHdr
.dwDstUser
= size
;
584 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
585 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
586 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
587 This
->acmStreamHdr
.cbDstLength
= This
->acmStreamHdr
.dwDstUser
;
589 /* need to prepare stream? */
590 This
->acmStreamHdr
.pbSrc
= buffer
;
591 This
->acmStreamHdr
.cbSrcLength
= buffersize
;
592 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
593 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
594 This
->acmStreamHdr
.pbSrc
= NULL
;
595 This
->acmStreamHdr
.cbSrcLength
= 0;
596 return AVIERR_COMPRESSOR
;
600 /* now do the conversion */
601 /* FIXME: use ACM_CONVERTF_* flags */
602 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
603 hr
= AVIERR_COMPRESSOR
;
607 This
->acmStreamHdr
.pbSrc
= NULL
;
608 This
->acmStreamHdr
.cbSrcLength
= 0;
613 return IAVIStream_Write(This
->pStream
,-1,This
->acmStreamHdr
.cbDstLengthUsed
/
614 This
->lpOutFormat
->nBlockAlign
,This
->acmStreamHdr
.pbDst
,
615 This
->acmStreamHdr
.cbDstLengthUsed
,flags
,sampwritten
,
619 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
, LONG start
,
622 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
624 TRACE("(%p,%ld,%ld)\n", iface
, start
, samples
);
626 /* check parameters */
627 if (start
< 0 || samples
< 0)
628 return AVIERR_BADPARAM
;
630 /* Delete before start of stream? */
631 if ((DWORD
)(start
+ samples
) < This
->sInfo
.dwStart
)
634 /* Delete after end of stream? */
635 if ((DWORD
)start
> This
->sInfo
.dwLength
)
638 /* For the rest we need write capability */
639 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
640 return AVIERR_READONLY
;
642 /* A compressor is also necessary */
643 if (This
->has
== NULL
)
644 return AVIERR_NOCOMPRESSOR
;
646 /* map our positions to pStream positions */
647 CONVERT_THIS_to_STREAM(&start
);
648 CONVERT_THIS_to_STREAM(&samples
);
650 return IAVIStream_Delete(This
->pStream
, start
, samples
);
653 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
, DWORD fcc
,
654 LPVOID lp
, LPLONG lpread
)
656 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
658 TRACE("(%p,0x%08lX,%p,%p)\n", iface
, fcc
, lp
, lpread
);
660 assert(This
->pStream
!= NULL
);
662 return IAVIStream_ReadData(This
->pStream
, fcc
, lp
, lpread
);
665 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
, DWORD fcc
,
666 LPVOID lp
, LONG size
)
668 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
670 TRACE("(%p,0x%08lx,%p,%ld)\n", iface
, fcc
, lp
, size
);
672 assert(This
->pStream
!= NULL
);
674 return IAVIStream_WriteData(This
->pStream
, fcc
, lp
, size
);
677 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,
678 LPAVISTREAMINFOW info
, LONG infolen
)
680 FIXME("(%p,%p,%ld): stub\n", iface
, info
, infolen
);
685 /***********************************************************************/
687 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
)
692 assert(This
!= NULL
);
693 assert(This
->pStream
!= NULL
);
695 if (This
->has
!= NULL
)
698 if (This
->lpInFormat
== NULL
) {
699 /* decode or encode the data from pStream */
700 hr
= AVIStreamFormatSize(This
->pStream
, This
->sInfo
.dwStart
, &This
->cbInFormat
);
703 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbInFormat
);
704 if (This
->lpInFormat
== NULL
)
705 return AVIERR_MEMORY
;
707 hr
= IAVIStream_ReadFormat(This
->pStream
, This
->sInfo
.dwStart
,
708 This
->lpInFormat
, &This
->cbInFormat
);
712 if (This
->lpOutFormat
== NULL
) {
713 /* we must decode to default format */
714 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
715 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
716 if (This
->lpOutFormat
== NULL
)
717 return AVIERR_MEMORY
;
719 This
->lpOutFormat
->wFormatTag
= WAVE_FORMAT_PCM
;
720 if (acmFormatSuggest(NULL
, This
->lpInFormat
, This
->lpOutFormat
,
721 This
->cbOutFormat
, ACM_FORMATSUGGESTF_WFORMATTAG
) != S_OK
)
722 return AVIERR_NOCOMPRESSOR
;
724 } else if (This
->lpOutFormat
== NULL
)
725 return AVIERR_ERROR
; /* To what should I encode? */
727 if (acmStreamOpen(&This
->has
, NULL
, This
->lpInFormat
, This
->lpOutFormat
,
728 NULL
, 0, 0, ACM_STREAMOPENF_NONREALTIME
) != S_OK
)
729 return AVIERR_NOCOMPRESSOR
;
731 /* update AVISTREAMINFO structure */
732 This
->sInfo
.dwSampleSize
= This
->lpOutFormat
->nBlockAlign
;
733 This
->sInfo
.dwScale
= This
->lpOutFormat
->nBlockAlign
;
734 This
->sInfo
.dwRate
= This
->lpOutFormat
->nAvgBytesPerSec
;
735 This
->sInfo
.dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
736 SetRectEmpty(&This
->sInfo
.rcFrame
);
738 /* convert positions ansd sizes to output format */
739 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwStart
);
740 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwLength
);
741 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwSuggestedBufferSize
);