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 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
59 ACMStream_fnQueryInterface,
64 ACMStream_fnFindSample,
65 ACMStream_fnReadFormat,
66 ACMStream_fnSetFormat,
71 ACMStream_fnWriteData,
75 typedef struct _IAVIStreamImpl {
77 IAVIStreamVtbl *lpVtbl;
80 /* IAVIStream stuff */
86 LPWAVEFORMATEX lpInFormat;
89 LPWAVEFORMATEX lpOutFormat;
92 ACMSTREAMHEADER acmStreamHdr;
95 /***********************************************************************/
97 #define CONVERT_STREAM_to_THIS(a) { \
98 acmStreamSize(This->has,(a)*This->lpInFormat->nBlockAlign,\
99 &(a), ACM_STREAMSIZEF_SOURCE); \
100 (a) /= This->lpOutFormat->nBlockAlign; }
101 #define CONVERT_THIS_to_STREAM(a) { \
102 acmStreamSize(This->has,(a)*This->lpOutFormat->nBlockAlign,\
103 &(a), ACM_STREAMSIZEF_DESTINATION); \
104 (a) /= This->lpInFormat->nBlockAlign; }
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 = (IAVIStreamImpl*)LocalAlloc(LPTR, sizeof(IAVIStreamImpl));
119 return AVIERR_MEMORY;
121 pstream->lpVtbl = &iacmst;
123 hr = IUnknown_QueryInterface((IUnknown*)pstream, riid, ppv);
125 LocalFree((HLOCAL)pstream);
130 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
131 REFIID refiid, LPVOID *obj)
133 ICOM_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 ICOM_THIS(IAVIStreamImpl,iface);
152 TRACE("(%p) -> %ld\n", iface, This->ref + 1);
154 /* also add reference to the nested stream */
155 if (This->pStream != NULL)
156 IAVIStream_AddRef(This->pStream);
158 return ++(This->ref);
161 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
163 ICOM_THIS(IAVIStreamImpl,iface);
165 TRACE("(%p) -> %ld\n", iface, This->ref - 1);
167 if (This->ref == 0) {
169 if (This->has != NULL) {
170 if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
171 acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
172 acmStreamClose(This->has, 0);
175 if (This->acmStreamHdr.pbSrc != NULL) {
176 GlobalFreePtr(This->acmStreamHdr.pbSrc);
177 This->acmStreamHdr.pbSrc = NULL;
179 if (This->acmStreamHdr.pbDst != NULL) {
180 GlobalFreePtr(This->acmStreamHdr.pbDst);
181 This->acmStreamHdr.pbDst = NULL;
183 if (This->lpInFormat != NULL) {
184 GlobalFreePtr(This->lpInFormat);
185 This->lpInFormat = NULL;
186 This->cbInFormat = 0;
188 if (This->lpOutFormat != NULL) {
189 GlobalFreePtr(This->lpOutFormat);
190 This->lpOutFormat = NULL;
191 This->cbOutFormat = 0;
193 if (This->pStream != NULL) {
194 IAVIStream_Release(This->pStream);
195 This->pStream = NULL;
197 LocalFree((HLOCAL)This);
202 /* also release reference to the nested stream */
203 if (This->pStream != NULL)
204 IAVIStream_Release(This->pStream);
209 /* lParam1: PAVISTREAM
210 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
212 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
215 ICOM_THIS(IAVIStreamImpl,iface);
217 TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
219 /* check for swapped parameters */
220 if ((LPVOID)lParam1 != NULL &&
221 ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
222 register LPARAM tmp = lParam1;
228 if ((LPVOID)lParam1 == NULL)
229 return AVIERR_BADPARAM;
231 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
232 if (This->sInfo.fccType != streamtypeAUDIO)
233 return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
235 This->sInfo.fccHandler = 0; /* be paranoid */
237 /* FIXME: check ACM version? Which version does we need? */
239 if ((LPVOID)lParam2 != NULL) {
240 /* We only need the format from the compress-options */
241 if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
242 lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
244 if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
245 This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
247 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
249 This->lpOutFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, This->cbOutFormat);
250 if (This->lpOutFormat == NULL)
251 return AVIERR_MEMORY;
253 memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
255 This->lpOutFormat = NULL;
256 This->cbOutFormat = 0;
259 This->pStream = (PAVISTREAM)lParam1;
260 IAVIStream_AddRef(This->pStream);
265 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
268 ICOM_THIS(IAVIStreamImpl,iface);
270 TRACE("(%p,%p,%ld)\n", iface, psi, size);
273 return AVIERR_BADPARAM;
275 return AVIERR_BADSIZE;
277 /* Need codec to correct some values in structure */
278 if (This->has == NULL) {
279 HRESULT hr = AVIFILE_OpenCompressor(This);
285 memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
287 if (size < (LONG)sizeof(This->sInfo))
288 return AVIERR_BUFFERTOOSMALL;
292 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
295 ICOM_THIS(IAVIStreamImpl,iface);
297 TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
299 if (flags & FIND_FROM_START) {
300 pos = This->sInfo.dwStart;
301 flags &= ~(FIND_FROM_START|FIND_PREV);
305 /* convert pos from our 'space' to This->pStream's one */
306 CONVERT_THIS_to_STREAM(pos);
309 pos = IAVIStream_FindSample(This->pStream, pos, flags);
312 /* convert pos back to our 'space' if it's no size or physical pos */
313 if ((flags & FIND_RET) == 0)
314 CONVERT_STREAM_to_THIS(pos);
320 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
321 LPVOID format, LONG *formatsize)
323 ICOM_THIS(IAVIStreamImpl,iface);
325 TRACE("(%p,%ld,%p,%p)\n", iface, pos, format, formatsize);
327 if (formatsize == NULL)
328 return AVIERR_BADPARAM;
330 if (This->has == NULL) {
331 HRESULT hr = AVIFILE_OpenCompressor(This);
337 /* only interested in needed buffersize? */
338 if (format == NULL || *formatsize <= 0) {
339 *formatsize = This->cbOutFormat;
344 /* copy initial format (only as much as will fit) */
345 memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
346 if (*formatsize < This->cbOutFormat) {
347 *formatsize = This->cbOutFormat;
348 return AVIERR_BUFFERTOOSMALL;
351 *formatsize = This->cbOutFormat;
355 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
356 LPVOID format, LONG formatsize)
358 ICOM_THIS(IAVIStreamImpl,iface);
362 TRACE("(%p,%ld,%p,%ld)\n", iface, pos, format, formatsize);
364 /* check parameters */
365 if (format == NULL || formatsize <= 0)
366 return AVIERR_BADPARAM;
368 /* Input format already known?
369 * Changing is unsupported, but be quiet if it's the same */
370 if (This->lpInFormat != NULL) {
371 if (This->cbInFormat != formatsize ||
372 memcmp(format, This->lpInFormat, formatsize) != 0)
373 return AVIERR_UNSUPPORTED;
378 /* Does the nested stream support writing? */
379 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
380 return AVIERR_READONLY;
382 This->lpInFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GMEM_MOVEABLE, formatsize);
383 if (This->lpInFormat == NULL)
384 return AVIERR_MEMORY;
385 This->cbInFormat = formatsize;
386 memcpy(This->lpInFormat, format, formatsize);
388 /* initialize formats and get compressor */
389 hr = AVIFILE_OpenCompressor(This);
393 CONVERT_THIS_to_STREAM(pos);
395 /* tell the nested stream the new format */
396 return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
400 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
401 LONG samples, LPVOID buffer,
402 LONG buffersize, LPLONG bytesread,
405 ICOM_THIS(IAVIStreamImpl,iface);
410 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", iface, start, samples, buffer,
411 buffersize, bytesread, samplesread);
413 /* clear return parameters if given */
414 if (bytesread != NULL)
416 if (samplesread != NULL)
419 /* Do we have our compressor? */
420 if (This->has == NULL) {
421 hr = AVIFILE_OpenCompressor(This);
427 /* only need to pass through? */
428 if (This->cbInFormat == This->cbOutFormat &&
429 memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
430 return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
431 bytesread, samplesread);
434 /* read as much as fit? */
436 samples = buffersize / This->lpOutFormat->nBlockAlign;
437 /* limit to buffersize */
438 if (samples * This->lpOutFormat->nBlockAlign > buffersize)
439 samples = buffersize / This->lpOutFormat->nBlockAlign;
441 /* only return needed size? */
442 if (buffer == NULL || buffersize <= 0 || samples == 0) {
443 if (bytesread == NULL && samplesread == NULL)
444 return AVIERR_BADPARAM;
446 if (bytesread != NULL)
447 *bytesread = samples * This->lpOutFormat->nBlockAlign;
448 if (samplesread != NULL)
449 *samplesread = samples;
454 /* map our positions to pStream positions */
455 CONVERT_THIS_to_STREAM(start);
457 /* our needed internal buffersize */
458 size = samples * This->lpInFormat->nBlockAlign;
460 /* Need to free destination buffer used for writing? */
461 if (This->acmStreamHdr.pbDst != NULL) {
462 GlobalFreePtr(This->acmStreamHdr.pbDst);
463 This->acmStreamHdr.pbDst = NULL;
464 This->acmStreamHdr.dwDstUser = 0;
467 /* need bigger source buffer? */
468 if (This->acmStreamHdr.pbSrc == NULL ||
469 This->acmStreamHdr.dwSrcUser < size) {
470 if (This->acmStreamHdr.pbSrc == NULL)
471 This->acmStreamHdr.pbSrc = GlobalAllocPtr(GMEM_MOVEABLE, size);
473 This->acmStreamHdr.pbSrc = GlobalReAllocPtr(This->acmStreamHdr.pbSrc,
474 size, GMEM_MOVEABLE);
475 if (This->acmStreamHdr.pbSrc == NULL)
476 return AVIERR_MEMORY;
477 This->acmStreamHdr.dwSrcUser = size;
480 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
481 This->acmStreamHdr.cbSrcLengthUsed = 0;
482 This->acmStreamHdr.cbDstLengthUsed = 0;
483 This->acmStreamHdr.cbSrcLength = size;
485 /* read source data */
486 hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
487 This->acmStreamHdr.cbSrcLength,
488 &This->acmStreamHdr.cbSrcLength, NULL);
489 if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
492 /* need to prepare stream? */
493 This->acmStreamHdr.pbDst = buffer;
494 This->acmStreamHdr.cbDstLength = buffersize;
495 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
496 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
497 This->acmStreamHdr.pbDst = NULL;
498 This->acmStreamHdr.cbDstLength = 0;
499 return AVIERR_COMPRESSOR;
503 /* now do the conversion */
504 /* FIXME: use ACM_CONVERTF_* flags */
505 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
506 hr = AVIERR_COMPRESSOR;
508 This->acmStreamHdr.pbDst = NULL;
509 This->acmStreamHdr.cbDstLength = 0;
511 /* fill out return parameters if given */
512 if (bytesread != NULL)
513 *bytesread = This->acmStreamHdr.cbDstLengthUsed;
514 if (samplesread != NULL)
516 This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
521 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
522 LONG samples, LPVOID buffer,
523 LONG buffersize, DWORD flags,
527 ICOM_THIS(IAVIStreamImpl,iface);
532 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n", iface, start, samples,
533 buffer, buffersize, flags, sampwritten, byteswritten);
535 /* clear return parameters if given */
536 if (sampwritten != NULL)
538 if (byteswritten != NULL)
541 /* check parameters */
542 if (buffer == NULL && (buffersize > 0 || samples > 0))
543 return AVIERR_BADPARAM;
545 /* Have we write capability? */
546 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
547 return AVIERR_READONLY;
549 /* also need a compressor */
550 if (This->has == NULL)
551 return AVIERR_NOCOMPRESSOR;
553 /* map our sizes to pStream sizes */
555 CONVERT_THIS_to_STREAM(size);
556 CONVERT_THIS_to_STREAM(start);
558 /* no bytes to write? -- short circuit */
560 return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
561 flags, sampwritten, byteswritten);
564 /* Need to free source buffer used for reading? */
565 if (This->acmStreamHdr.pbSrc != NULL) {
566 GlobalFreePtr(This->acmStreamHdr.pbSrc);
567 This->acmStreamHdr.pbSrc = NULL;
568 This->acmStreamHdr.dwSrcUser = 0;
571 /* Need bigger destination buffer? */
572 if (This->acmStreamHdr.pbDst == NULL ||
573 This->acmStreamHdr.dwDstUser < size) {
574 if (This->acmStreamHdr.pbDst == NULL)
575 This->acmStreamHdr.pbDst = GlobalAllocPtr(GMEM_MOVEABLE, size);
577 This->acmStreamHdr.pbDst = GlobalReAllocPtr(This->acmStreamHdr.pbDst,
578 size, GMEM_MOVEABLE);
579 if (This->acmStreamHdr.pbDst == NULL)
580 return AVIERR_MEMORY;
581 This->acmStreamHdr.dwDstUser = size;
583 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
584 This->acmStreamHdr.cbSrcLengthUsed = 0;
585 This->acmStreamHdr.cbDstLengthUsed = 0;
586 This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser;
588 /* need to prepare stream? */
589 This->acmStreamHdr.pbSrc = buffer;
590 This->acmStreamHdr.cbSrcLength = buffersize;
591 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
592 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
593 This->acmStreamHdr.pbSrc = NULL;
594 This->acmStreamHdr.cbSrcLength = 0;
595 return AVIERR_COMPRESSOR;
599 /* now do the conversion */
600 /* FIXME: use ACM_CONVERTF_* flags */
601 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
602 hr = AVIERR_COMPRESSOR;
606 This->acmStreamHdr.pbSrc = NULL;
607 This->acmStreamHdr.cbSrcLength = 0;
612 return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
613 This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
614 This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
618 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
621 ICOM_THIS(IAVIStreamImpl,iface);
623 TRACE("(%p,%ld,%ld)\n", iface, start, samples);
625 /* check parameters */
626 if (start < 0 || samples < 0)
627 return AVIERR_BADPARAM;
629 /* Delete before start of stream? */
630 if ((DWORD)(start + samples) < This->sInfo.dwStart)
633 /* Delete after end of stream? */
634 if ((DWORD)start > This->sInfo.dwLength)
637 /* For the rest we need write capability */
638 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
639 return AVIERR_READONLY;
641 /* A compressor is also necessary */
642 if (This->has == NULL)
643 return AVIERR_NOCOMPRESSOR;
645 /* map our positions to pStream positions */
646 CONVERT_THIS_to_STREAM(start);
647 CONVERT_THIS_to_STREAM(samples);
649 return IAVIStream_Delete(This->pStream, start, samples);
652 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
653 LPVOID lp, LPLONG lpread)
655 ICOM_THIS(IAVIStreamImpl,iface);
657 TRACE("(%p,0x%08lX,%p,%p)\n", iface, fcc, lp, lpread);
659 assert(This->pStream != NULL);
661 return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
664 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
665 LPVOID lp, LONG size)
667 ICOM_THIS(IAVIStreamImpl,iface);
669 TRACE("(%p,0x%08lx,%p,%ld)\n", iface, fcc, lp, size);
671 assert(This->pStream != NULL);
673 return IAVIStream_WriteData(This->pStream, fcc, lp, size);
676 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
677 LPAVISTREAMINFOW info, LONG infolen)
679 FIXME("(%p,%p,%ld): stub\n", iface, info, infolen);
684 /***********************************************************************/
686 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
691 assert(This != NULL);
692 assert(This->pStream != NULL);
694 if (This->has != NULL)
697 if (This->lpInFormat == NULL) {
698 /* decode or encode the data from pStream */
699 hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
702 This->lpInFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GMEM_MOVEABLE, This->cbInFormat);
703 if (This->lpInFormat == NULL)
704 return AVIERR_MEMORY;
706 hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
707 This->lpInFormat, &This->cbInFormat);
711 if (This->lpOutFormat == NULL) {
712 /* we must decode to default format */
713 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
714 This->lpOutFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, This->cbOutFormat);
715 if (This->lpOutFormat == NULL)
716 return AVIERR_MEMORY;
718 This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
719 if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
720 This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
721 return AVIERR_NOCOMPRESSOR;
723 } else if (This->lpOutFormat == NULL)
724 return AVIERR_ERROR; /* To what should I encode? */
726 if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
727 NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
728 return AVIERR_NOCOMPRESSOR;
730 /* update AVISTREAMINFO structure */
731 This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
732 This->sInfo.dwScale = This->lpOutFormat->nBlockAlign;
733 This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec;
734 This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT;
735 SetRectEmpty(&This->sInfo.rcFrame);
737 /* convert positions ansd sizes to output format */
738 CONVERT_STREAM_to_THIS(This->sInfo.dwStart);
739 CONVERT_STREAM_to_THIS(This->sInfo.dwLength);
740 CONVERT_STREAM_to_THIS(This->sInfo.dwSuggestedBufferSize);