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
32 #include "avifile_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
38 /***********************************************************************/
40 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
41 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream*iface);
42 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface);
43 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
44 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
45 static LONG WINAPI ACMStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
46 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
47 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
48 static HRESULT WINAPI ACMStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
49 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
50 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
51 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
52 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
53 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
55 static const struct IAVIStreamVtbl iacmst = {
56 ACMStream_fnQueryInterface,
61 ACMStream_fnFindSample,
62 ACMStream_fnReadFormat,
63 ACMStream_fnSetFormat,
68 ACMStream_fnWriteData,
72 typedef struct _IAVIStreamImpl {
74 const IAVIStreamVtbl *lpVtbl;
77 /* IAVIStream stuff */
83 LPWAVEFORMATEX lpInFormat;
86 LPWAVEFORMATEX lpOutFormat;
89 ACMSTREAMHEADER acmStreamHdr;
92 /***********************************************************************/
94 #define CONVERT_STREAM_to_THIS(a) do { \
96 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
97 &__bytes, ACM_STREAMSIZEF_SOURCE); \
98 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
100 #define CONVERT_THIS_to_STREAM(a) do { \
102 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
103 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
104 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
106 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This);
108 HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppv)
110 IAVIStreamImpl *pstream;
113 assert(riid != NULL && ppv != NULL);
117 pstream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAVIStreamImpl));
119 return AVIERR_MEMORY;
121 pstream->lpVtbl = &iacmst;
123 hr = IAVIStream_QueryInterface((IAVIStream*)pstream, riid, ppv);
125 HeapFree(GetProcessHeap(), 0, pstream);
130 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
131 REFIID refiid, LPVOID *obj)
133 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
135 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
137 if (IsEqualGUID(&IID_IUnknown, refiid) ||
138 IsEqualGUID(&IID_IAVIStream, refiid)) {
140 IAVIStream_AddRef(iface);
145 return OLE_E_ENUM_NOMORE;
148 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface)
150 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
151 ULONG ref = InterlockedIncrement(&This->ref);
153 TRACE("(%p) -> %d\n", iface, ref);
155 /* also add reference to the nested stream */
156 if (This->pStream != NULL)
157 IAVIStream_AddRef(This->pStream);
162 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
164 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
165 ULONG ref = InterlockedDecrement(&This->ref);
167 TRACE("(%p) -> %d\n", iface, ref);
171 if (This->has != NULL) {
172 if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
173 acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
174 acmStreamClose(This->has, 0);
177 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
178 This->acmStreamHdr.pbSrc = NULL;
179 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
180 This->acmStreamHdr.pbDst = NULL;
181 if (This->lpInFormat != NULL) {
182 HeapFree(GetProcessHeap(), 0, This->lpInFormat);
183 This->lpInFormat = NULL;
184 This->cbInFormat = 0;
186 if (This->lpOutFormat != NULL) {
187 HeapFree(GetProcessHeap(), 0, This->lpOutFormat);
188 This->lpOutFormat = NULL;
189 This->cbOutFormat = 0;
191 if (This->pStream != NULL) {
192 IAVIStream_Release(This->pStream);
193 This->pStream = NULL;
195 HeapFree(GetProcessHeap(), 0, This);
200 /* also release reference to the nested stream */
201 if (This->pStream != NULL)
202 IAVIStream_Release(This->pStream);
207 /* lParam1: PAVISTREAM
208 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
210 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
213 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
215 TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
217 /* check for swapped parameters */
218 if ((LPVOID)lParam1 != NULL &&
219 ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
220 register LPARAM tmp = lParam1;
226 if ((LPVOID)lParam1 == NULL)
227 return AVIERR_BADPARAM;
229 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
230 if (This->sInfo.fccType != streamtypeAUDIO)
231 return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
233 This->sInfo.fccHandler = 0; /* be paranoid */
235 /* FIXME: check ACM version? Which version does we need? */
237 if ((LPVOID)lParam2 != NULL) {
238 /* We only need the format from the compress-options */
239 if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
240 lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
242 if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
243 This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
245 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
247 This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
248 if (This->lpOutFormat == NULL)
249 return AVIERR_MEMORY;
251 memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
253 This->lpOutFormat = NULL;
254 This->cbOutFormat = 0;
257 This->pStream = (PAVISTREAM)lParam1;
258 IAVIStream_AddRef(This->pStream);
263 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
266 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
268 TRACE("(%p,%p,%d)\n", iface, psi, size);
271 return AVIERR_BADPARAM;
273 return AVIERR_BADSIZE;
275 /* Need codec to correct some values in structure */
276 if (This->has == NULL) {
277 HRESULT hr = AVIFILE_OpenCompressor(This);
283 memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
285 if (size < (LONG)sizeof(This->sInfo))
286 return AVIERR_BUFFERTOOSMALL;
290 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
293 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
295 TRACE("(%p,%d,0x%08X)\n",iface,pos,flags);
297 if (flags & FIND_FROM_START) {
298 pos = This->sInfo.dwStart;
299 flags &= ~(FIND_FROM_START|FIND_PREV);
303 /* convert pos from our 'space' to This->pStream's one */
304 CONVERT_THIS_to_STREAM(&pos);
307 pos = IAVIStream_FindSample(This->pStream, pos, flags);
310 /* convert pos back to our 'space' if it's no size or physical pos */
311 if ((flags & FIND_RET) == 0)
312 CONVERT_STREAM_to_THIS(&pos);
318 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
319 LPVOID format, LONG *formatsize)
321 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
323 TRACE("(%p,%d,%p,%p)\n", iface, pos, format, formatsize);
325 if (formatsize == NULL)
326 return AVIERR_BADPARAM;
328 if (This->has == NULL) {
329 HRESULT hr = AVIFILE_OpenCompressor(This);
335 /* only interested in needed buffersize? */
336 if (format == NULL || *formatsize <= 0) {
337 *formatsize = This->cbOutFormat;
342 /* copy initial format (only as much as will fit) */
343 memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
344 if (*formatsize < This->cbOutFormat) {
345 *formatsize = This->cbOutFormat;
346 return AVIERR_BUFFERTOOSMALL;
349 *formatsize = This->cbOutFormat;
353 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
354 LPVOID format, LONG formatsize)
356 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
360 TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);
362 /* check parameters */
363 if (format == NULL || formatsize <= 0)
364 return AVIERR_BADPARAM;
366 /* Input format already known?
367 * Changing is unsupported, but be quiet if it's the same */
368 if (This->lpInFormat != NULL) {
369 if (This->cbInFormat != formatsize ||
370 memcmp(format, This->lpInFormat, formatsize) != 0)
371 return AVIERR_UNSUPPORTED;
376 /* Does the nested stream support writing? */
377 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
378 return AVIERR_READONLY;
380 This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, formatsize);
381 if (This->lpInFormat == NULL)
382 return AVIERR_MEMORY;
383 This->cbInFormat = formatsize;
384 memcpy(This->lpInFormat, format, formatsize);
386 /* initialize formats and get compressor */
387 hr = AVIFILE_OpenCompressor(This);
391 CONVERT_THIS_to_STREAM(&pos);
393 /* tell the nested stream the new format */
394 return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
398 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
399 LONG samples, LPVOID buffer,
400 LONG buffersize, LPLONG bytesread,
403 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
408 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer,
409 buffersize, bytesread, samplesread);
411 /* clear return parameters if given */
412 if (bytesread != NULL)
414 if (samplesread != NULL)
417 /* Do we have our compressor? */
418 if (This->has == NULL) {
419 hr = AVIFILE_OpenCompressor(This);
425 /* only need to pass through? */
426 if (This->cbInFormat == This->cbOutFormat &&
427 memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
428 return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
429 bytesread, samplesread);
432 /* read as much as fit? */
434 samples = buffersize / This->lpOutFormat->nBlockAlign;
435 /* limit to buffersize */
436 if (samples * This->lpOutFormat->nBlockAlign > buffersize)
437 samples = buffersize / This->lpOutFormat->nBlockAlign;
439 /* only return needed size? */
440 if (buffer == NULL || buffersize <= 0 || samples == 0) {
441 if (bytesread == NULL && samplesread == NULL)
442 return AVIERR_BADPARAM;
444 if (bytesread != NULL)
445 *bytesread = samples * This->lpOutFormat->nBlockAlign;
446 if (samplesread != NULL)
447 *samplesread = samples;
452 /* map our positions to pStream positions */
453 CONVERT_THIS_to_STREAM(&start);
455 /* our needed internal buffersize */
456 size = samples * This->lpInFormat->nBlockAlign;
458 /* Need to free destination buffer used for writing? */
459 if (This->acmStreamHdr.pbDst != NULL) {
460 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
461 This->acmStreamHdr.pbDst = NULL;
462 This->acmStreamHdr.dwDstUser = 0;
465 /* need bigger source buffer? */
466 if (This->acmStreamHdr.pbSrc == NULL ||
467 This->acmStreamHdr.dwSrcUser < size) {
468 if (This->acmStreamHdr.pbSrc == NULL)
469 This->acmStreamHdr.pbSrc = HeapAlloc(GetProcessHeap(), 0, size);
471 This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc, size);
472 if (This->acmStreamHdr.pbSrc == NULL)
473 return AVIERR_MEMORY;
474 This->acmStreamHdr.dwSrcUser = size;
477 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
478 This->acmStreamHdr.cbSrcLengthUsed = 0;
479 This->acmStreamHdr.cbDstLengthUsed = 0;
480 This->acmStreamHdr.cbSrcLength = size;
482 /* read source data */
483 hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
484 This->acmStreamHdr.cbSrcLength,
485 (LONG *)&This->acmStreamHdr.cbSrcLength, NULL);
486 if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
489 /* need to prepare stream? */
490 This->acmStreamHdr.pbDst = buffer;
491 This->acmStreamHdr.cbDstLength = buffersize;
492 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
493 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
494 This->acmStreamHdr.pbDst = NULL;
495 This->acmStreamHdr.cbDstLength = 0;
496 return AVIERR_COMPRESSOR;
500 /* now do the conversion */
501 /* FIXME: use ACM_CONVERTF_* flags */
502 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
503 hr = AVIERR_COMPRESSOR;
505 This->acmStreamHdr.pbDst = NULL;
506 This->acmStreamHdr.cbDstLength = 0;
508 /* fill out return parameters if given */
509 if (bytesread != NULL)
510 *bytesread = This->acmStreamHdr.cbDstLengthUsed;
511 if (samplesread != NULL)
513 This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
518 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
519 LONG samples, LPVOID buffer,
520 LONG buffersize, DWORD flags,
524 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
529 TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples,
530 buffer, buffersize, flags, sampwritten, byteswritten);
532 /* clear return parameters if given */
533 if (sampwritten != NULL)
535 if (byteswritten != NULL)
538 /* check parameters */
539 if (buffer == NULL && (buffersize > 0 || samples > 0))
540 return AVIERR_BADPARAM;
542 /* Have we write capability? */
543 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
544 return AVIERR_READONLY;
546 /* also need a compressor */
547 if (This->has == NULL)
548 return AVIERR_NOCOMPRESSOR;
550 /* map our sizes to pStream sizes */
552 CONVERT_THIS_to_STREAM(&size);
553 CONVERT_THIS_to_STREAM(&start);
555 /* no bytes to write? -- short circuit */
557 return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
558 flags, sampwritten, byteswritten);
561 /* Need to free source buffer used for reading? */
562 if (This->acmStreamHdr.pbSrc != NULL) {
563 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
564 This->acmStreamHdr.pbSrc = NULL;
565 This->acmStreamHdr.dwSrcUser = 0;
568 /* Need bigger destination buffer? */
569 if (This->acmStreamHdr.pbDst == NULL ||
570 This->acmStreamHdr.dwDstUser < size) {
571 if (This->acmStreamHdr.pbDst == NULL)
572 This->acmStreamHdr.pbDst = HeapAlloc(GetProcessHeap(), 0, size);
574 This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbDst, size);
575 if (This->acmStreamHdr.pbDst == NULL)
576 return AVIERR_MEMORY;
577 This->acmStreamHdr.dwDstUser = size;
579 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
580 This->acmStreamHdr.cbSrcLengthUsed = 0;
581 This->acmStreamHdr.cbDstLengthUsed = 0;
582 This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser;
584 /* need to prepare stream? */
585 This->acmStreamHdr.pbSrc = buffer;
586 This->acmStreamHdr.cbSrcLength = buffersize;
587 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
588 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
589 This->acmStreamHdr.pbSrc = NULL;
590 This->acmStreamHdr.cbSrcLength = 0;
591 return AVIERR_COMPRESSOR;
595 /* now do the conversion */
596 /* FIXME: use ACM_CONVERTF_* flags */
597 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
598 hr = AVIERR_COMPRESSOR;
602 This->acmStreamHdr.pbSrc = NULL;
603 This->acmStreamHdr.cbSrcLength = 0;
608 return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
609 This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
610 This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
614 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
617 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
619 TRACE("(%p,%d,%d)\n", iface, start, samples);
621 /* check parameters */
622 if (start < 0 || samples < 0)
623 return AVIERR_BADPARAM;
625 /* Delete before start of stream? */
626 if ((DWORD)(start + samples) < This->sInfo.dwStart)
629 /* Delete after end of stream? */
630 if ((DWORD)start > This->sInfo.dwLength)
633 /* For the rest we need write capability */
634 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
635 return AVIERR_READONLY;
637 /* A compressor is also necessary */
638 if (This->has == NULL)
639 return AVIERR_NOCOMPRESSOR;
641 /* map our positions to pStream positions */
642 CONVERT_THIS_to_STREAM(&start);
643 CONVERT_THIS_to_STREAM(&samples);
645 return IAVIStream_Delete(This->pStream, start, samples);
648 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
649 LPVOID lp, LPLONG lpread)
651 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
653 TRACE("(%p,0x%08X,%p,%p)\n", iface, fcc, lp, lpread);
655 assert(This->pStream != NULL);
657 return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
660 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
661 LPVOID lp, LONG size)
663 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
665 TRACE("(%p,0x%08x,%p,%d)\n", iface, fcc, lp, size);
667 assert(This->pStream != NULL);
669 return IAVIStream_WriteData(This->pStream, fcc, lp, size);
672 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
673 LPAVISTREAMINFOW info, LONG infolen)
675 FIXME("(%p,%p,%d): stub\n", iface, info, infolen);
680 /***********************************************************************/
682 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
687 assert(This != NULL);
688 assert(This->pStream != NULL);
690 if (This->has != NULL)
693 if (This->lpInFormat == NULL) {
694 /* decode or encode the data from pStream */
695 hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
698 This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat);
699 if (This->lpInFormat == NULL)
700 return AVIERR_MEMORY;
702 hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
703 This->lpInFormat, &This->cbInFormat);
707 if (This->lpOutFormat == NULL) {
708 /* we must decode to default format */
709 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
710 This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
711 if (This->lpOutFormat == NULL)
712 return AVIERR_MEMORY;
714 This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
715 if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
716 This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
717 return AVIERR_NOCOMPRESSOR;
719 } else if (This->lpOutFormat == NULL)
720 return AVIERR_ERROR; /* To what should I encode? */
722 if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
723 NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
724 return AVIERR_NOCOMPRESSOR;
726 /* update AVISTREAMINFO structure */
727 This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
728 This->sInfo.dwScale = This->lpOutFormat->nBlockAlign;
729 This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec;
730 This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT;
731 SetRectEmpty(&This->sInfo.rcFrame);
733 /* convert positions ansd sizes to output format */
734 CONVERT_STREAM_to_THIS(&This->sInfo.dwStart);
735 CONVERT_STREAM_to_THIS(&This->sInfo.dwLength);
736 CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize);