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
30 #include "avifile_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
36 /***********************************************************************/
38 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
39 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream*iface);
40 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface);
41 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
42 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
43 static LONG WINAPI ACMStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
44 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
45 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
46 static HRESULT WINAPI ACMStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
47 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
48 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
49 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
50 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
51 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
53 struct ICOM_VTABLE(IAVIStream) iacmst = {
54 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
55 ACMStream_fnQueryInterface,
60 ACMStream_fnFindSample,
61 ACMStream_fnReadFormat,
62 ACMStream_fnSetFormat,
67 ACMStream_fnWriteData,
71 typedef struct _IAVIStreamImpl {
73 ICOM_VFIELD(IAVIStream);
76 /* IAVIStream stuff */
82 LPWAVEFORMATEX lpInFormat;
85 LPWAVEFORMATEX lpOutFormat;
88 ACMSTREAMHEADER acmStreamHdr;
91 /***********************************************************************/
93 #define CONVERT_STREAM_to_THIS(a) { \
94 acmStreamSize(This->has,(a)*This->lpInFormat->nBlockAlign,\
95 &(a), ACM_STREAMSIZEF_SOURCE); \
96 (a) /= This->lpOutFormat->nBlockAlign; }
97 #define CONVERT_THIS_to_STREAM(a) { \
98 acmStreamSize(This->has,(a)*This->lpOutFormat->nBlockAlign,\
99 &(a), ACM_STREAMSIZEF_DESTINATION); \
100 (a) /= This->lpInFormat->nBlockAlign; }
102 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This);
104 HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppv)
106 IAVIStreamImpl *pstream;
109 assert(riid != NULL && ppv != NULL);
113 pstream = (IAVIStreamImpl*)LocalAlloc(LPTR, sizeof(IAVIStreamImpl));
115 return AVIERR_MEMORY;
117 ICOM_VTBL(pstream) = &iacmst;
119 hr = IUnknown_QueryInterface((IUnknown*)pstream, riid, ppv);
121 LocalFree((HLOCAL)pstream);
126 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
127 REFIID refiid, LPVOID *obj)
129 ICOM_THIS(IAVIStreamImpl,iface);
131 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
133 if (IsEqualGUID(&IID_IUnknown, refiid) ||
134 IsEqualGUID(&IID_IAVIStream, refiid)) {
136 IAVIStream_AddRef(iface);
141 return OLE_E_ENUM_NOMORE;
144 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface)
146 ICOM_THIS(IAVIStreamImpl,iface);
148 TRACE("(%p) -> %ld\n", iface, This->ref + 1);
150 /* also add reference to the nested stream */
151 if (This->pStream != NULL)
152 IAVIStream_AddRef(This->pStream);
154 return ++(This->ref);
157 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
159 ICOM_THIS(IAVIStreamImpl,iface);
161 TRACE("(%p) -> %ld\n", iface, This->ref - 1);
163 if (This->ref == 0) {
165 if (This->has != NULL) {
166 if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
167 acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
168 acmStreamClose(This->has, 0);
171 if (This->acmStreamHdr.pbSrc != NULL) {
172 GlobalFreePtr(This->acmStreamHdr.pbSrc);
173 This->acmStreamHdr.pbSrc = NULL;
175 if (This->acmStreamHdr.pbDst != NULL) {
176 GlobalFreePtr(This->acmStreamHdr.pbDst);
177 This->acmStreamHdr.pbDst = NULL;
179 if (This->lpInFormat != NULL) {
180 GlobalFreePtr(This->lpInFormat);
181 This->lpInFormat = NULL;
182 This->cbInFormat = 0;
184 if (This->lpOutFormat != NULL) {
185 GlobalFreePtr(This->lpOutFormat);
186 This->lpOutFormat = NULL;
187 This->cbOutFormat = 0;
189 if (This->pStream != NULL) {
190 IAVIStream_Release(This->pStream);
191 This->pStream = NULL;
193 LocalFree((HLOCAL)This);
198 /* also release reference to the nested stream */
199 if (This->pStream != NULL)
200 IAVIStream_Release(This->pStream);
205 /* lParam1: PAVISTREAM
206 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
208 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
211 ICOM_THIS(IAVIStreamImpl,iface);
213 TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
215 /* check for swapped parameters */
216 if ((LPVOID)lParam1 != NULL &&
217 ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
218 register LPARAM tmp = lParam1;
224 if ((LPVOID)lParam1 == NULL)
225 return AVIERR_BADPARAM;
227 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
228 if (This->sInfo.fccType != streamtypeAUDIO)
229 return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
231 This->sInfo.fccHandler = 0; /* be paranoid */
233 /* FIXME: check ACM version? Which version does we need? */
235 if ((LPVOID)lParam2 != NULL) {
236 /* We only need the format from the compress-options */
237 if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
238 lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
240 if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
241 This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
243 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
245 This->lpOutFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, This->cbOutFormat);
246 if (This->lpOutFormat == NULL)
247 return AVIERR_MEMORY;
249 memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
251 This->lpOutFormat = NULL;
252 This->cbOutFormat = 0;
255 This->pStream = (PAVISTREAM)lParam1;
256 IAVIStream_AddRef(This->pStream);
261 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
264 ICOM_THIS(IAVIStreamImpl,iface);
266 TRACE("(%p,%p,%ld)\n", iface, psi, size);
269 return AVIERR_BADPARAM;
271 return AVIERR_BADSIZE;
273 /* Need codec to correct some values in structure */
274 if (This->has == NULL) {
275 HRESULT hr = AVIFILE_OpenCompressor(This);
281 memcpy(psi, &This->sInfo, min(size, sizeof(This->sInfo)));
283 if (size < sizeof(This->sInfo))
284 return AVIERR_BUFFERTOOSMALL;
288 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
291 ICOM_THIS(IAVIStreamImpl,iface);
293 TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
295 if (flags & FIND_FROM_START) {
296 pos = This->sInfo.dwStart;
297 flags &= ~(FIND_FROM_START|FIND_PREV);
301 /* convert pos from our 'space' to This->pStream's one */
302 CONVERT_THIS_to_STREAM(pos);
305 pos = IAVIStream_FindSample(This->pStream, pos, flags);
308 /* convert pos back to our 'space' if it's no size or physical pos */
309 if ((flags & FIND_RET) == 0)
310 CONVERT_STREAM_to_THIS(pos);
316 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
317 LPVOID format, LONG *formatsize)
319 ICOM_THIS(IAVIStreamImpl,iface);
321 TRACE("(%p,%ld,%p,%p)\n", iface, pos, format, formatsize);
323 if (formatsize == NULL)
324 return AVIERR_BADPARAM;
326 if (This->has == NULL) {
327 HRESULT hr = AVIFILE_OpenCompressor(This);
333 /* only interested in needed buffersize? */
334 if (format == NULL || *formatsize <= 0) {
335 *formatsize = This->cbOutFormat;
340 /* copy initial format (only as much as will fit) */
341 memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
342 if (*formatsize < This->cbOutFormat) {
343 *formatsize = This->cbOutFormat;
344 return AVIERR_BUFFERTOOSMALL;
347 *formatsize = This->cbOutFormat;
351 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
352 LPVOID format, LONG formatsize)
354 ICOM_THIS(IAVIStreamImpl,iface);
358 TRACE("(%p,%ld,%p,%ld)\n", iface, pos, format, formatsize);
360 /* check parameters */
361 if (format == NULL || formatsize <= 0)
362 return AVIERR_BADPARAM;
364 /* Input format already known?
365 * Changing is unsupported, but be quiet if it's the same */
366 if (This->lpInFormat != NULL) {
367 if (This->cbInFormat != formatsize ||
368 memcmp(format, This->lpInFormat, formatsize) != 0)
369 return AVIERR_UNSUPPORTED;
374 /* Does the nested stream support writing? */
375 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
376 return AVIERR_READONLY;
378 This->lpInFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GMEM_MOVEABLE, formatsize);
379 if (This->lpInFormat == NULL)
380 return AVIERR_MEMORY;
381 This->cbInFormat = formatsize;
382 memcpy(This->lpInFormat, format, formatsize);
384 /* initialize formats and get compressor */
385 hr = AVIFILE_OpenCompressor(This);
389 CONVERT_THIS_to_STREAM(pos);
391 /* tell the nested stream the new format */
392 return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
396 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
397 LONG samples, LPVOID buffer,
398 LONG buffersize, LPLONG bytesread,
401 ICOM_THIS(IAVIStreamImpl,iface);
406 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", iface, start, samples, buffer,
407 buffersize, bytesread, samplesread);
409 /* clear return parameters if given */
410 if (bytesread != NULL)
412 if (samplesread != NULL)
415 /* Do we have our compressor? */
416 if (This->has == NULL) {
417 hr = AVIFILE_OpenCompressor(This);
423 /* only need to pass through? */
424 if (This->cbInFormat == This->cbOutFormat &&
425 memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
426 return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
427 bytesread, samplesread);
430 /* read as much as fit? */
432 samples = buffersize / This->lpOutFormat->nBlockAlign;
433 /* limit to buffersize */
434 if (samples * This->lpOutFormat->nBlockAlign > buffersize)
435 samples = buffersize / This->lpOutFormat->nBlockAlign;
437 /* only return needed size? */
438 if (buffer == NULL || buffersize <= 0 || samples == 0) {
439 if (bytesread == NULL && samplesread == NULL)
440 return AVIERR_BADPARAM;
442 if (bytesread != NULL)
443 *bytesread = samples * This->lpOutFormat->nBlockAlign;
444 if (samplesread != NULL)
445 *samplesread = samples;
450 /* map our positions to pStream positions */
451 CONVERT_THIS_to_STREAM(start);
453 /* our needed internal buffersize */
454 size = samples * This->lpInFormat->nBlockAlign;
456 /* Need to free destination buffer used for writing? */
457 if (This->acmStreamHdr.pbDst != NULL) {
458 GlobalFreePtr(This->acmStreamHdr.pbDst);
459 This->acmStreamHdr.pbDst = NULL;
460 This->acmStreamHdr.dwDstUser = 0;
463 /* need bigger source buffer? */
464 if (This->acmStreamHdr.pbSrc == NULL ||
465 This->acmStreamHdr.dwSrcUser < size) {
466 This->acmStreamHdr.pbSrc = GlobalReAllocPtr(This->acmStreamHdr.pbSrc,
467 size, GMEM_MOVEABLE);
468 if (This->acmStreamHdr.pbSrc == NULL)
469 return AVIERR_MEMORY;
470 This->acmStreamHdr.dwSrcUser = size;
473 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
474 This->acmStreamHdr.cbSrcLengthUsed = 0;
475 This->acmStreamHdr.cbDstLengthUsed = 0;
476 This->acmStreamHdr.cbSrcLength = size;
478 /* read source data */
479 hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
480 This->acmStreamHdr.cbSrcLength,
481 &This->acmStreamHdr.cbSrcLength, NULL);
482 if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
485 /* need to prepare stream? */
486 This->acmStreamHdr.pbDst = buffer;
487 This->acmStreamHdr.cbDstLength = buffersize;
488 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
489 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
490 This->acmStreamHdr.pbDst = NULL;
491 This->acmStreamHdr.cbDstLength = 0;
492 return AVIERR_COMPRESSOR;
496 /* now do the conversion */
497 /* FIXME: use ACM_CONVERTF_* flags */
498 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
499 hr = AVIERR_COMPRESSOR;
501 This->acmStreamHdr.pbDst = NULL;
502 This->acmStreamHdr.cbDstLength = 0;
504 /* fill out return parameters if given */
505 if (bytesread != NULL)
506 *bytesread = This->acmStreamHdr.cbDstLengthUsed;
507 if (samplesread != NULL)
509 This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
514 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
515 LONG samples, LPVOID buffer,
516 LONG buffersize, DWORD flags,
520 ICOM_THIS(IAVIStreamImpl,iface);
525 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n", iface, start, samples,
526 buffer, buffersize, flags, sampwritten, byteswritten);
528 /* clear return parameters if given */
529 if (sampwritten != NULL)
531 if (byteswritten != NULL)
534 /* check parameters */
535 if (buffer == NULL && (buffersize > 0 || samples > 0))
536 return AVIERR_BADPARAM;
538 /* Have we write capability? */
539 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
540 return AVIERR_READONLY;
542 /* also need a compressor */
543 if (This->has == NULL)
544 return AVIERR_NOCOMPRESSOR;
546 /* map our sizes to pStream sizes */
548 CONVERT_THIS_to_STREAM(size);
549 CONVERT_THIS_to_STREAM(start);
551 /* no bytes to write? -- short circuit */
553 return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
554 flags, sampwritten, byteswritten);
557 /* Need to free source buffer used for reading? */
558 if (This->acmStreamHdr.pbSrc != NULL) {
559 GlobalFreePtr(This->acmStreamHdr.pbSrc);
560 This->acmStreamHdr.pbSrc = NULL;
561 This->acmStreamHdr.dwSrcUser = 0;
564 /* Need bigger destination buffer? */
565 if (This->acmStreamHdr.pbDst == NULL ||
566 This->acmStreamHdr.dwDstUser < size) {
567 This->acmStreamHdr.pbDst = GlobalReAllocPtr(This->acmStreamHdr.pbDst,
568 size, GMEM_MOVEABLE);
569 if (This->acmStreamHdr.pbDst == NULL)
570 return AVIERR_MEMORY;
571 This->acmStreamHdr.dwDstUser = size;
573 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
574 This->acmStreamHdr.cbSrcLengthUsed = 0;
575 This->acmStreamHdr.cbDstLengthUsed = 0;
576 This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser;
578 /* need to prepare stream? */
579 This->acmStreamHdr.pbSrc = buffer;
580 This->acmStreamHdr.cbSrcLength = buffersize;
581 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
582 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
583 This->acmStreamHdr.pbSrc = NULL;
584 This->acmStreamHdr.cbSrcLength = 0;
585 return AVIERR_COMPRESSOR;
589 /* now do the conversion */
590 /* FIXME: use ACM_CONVERTF_* flags */
591 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
592 hr = AVIERR_COMPRESSOR;
596 This->acmStreamHdr.pbSrc = NULL;
597 This->acmStreamHdr.cbSrcLength = 0;
602 return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
603 This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
604 This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
608 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
611 ICOM_THIS(IAVIStreamImpl,iface);
613 TRACE("(%p,%ld,%ld)\n", iface, start, samples);
615 /* check parameters */
616 if (start < 0 || samples < 0)
617 return AVIERR_BADPARAM;
619 /* Delete before start of stream? */
620 if (start + samples < This->sInfo.dwStart)
623 /* Delete after end of stream? */
624 if (start > This->sInfo.dwLength)
627 /* For the rest we need write capability */
628 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
629 return AVIERR_READONLY;
631 /* A compressor is also neccessary */
632 if (This->has == NULL)
633 return AVIERR_NOCOMPRESSOR;
635 /* map our positions to pStream positions */
636 CONVERT_THIS_to_STREAM(start);
637 CONVERT_THIS_to_STREAM(samples);
639 return IAVIStream_Delete(This->pStream, start, samples);
642 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
643 LPVOID lp, LPLONG lpread)
645 ICOM_THIS(IAVIStreamImpl,iface);
647 TRACE("(%p,0x%08lX,%p,%p)\n", iface, fcc, lp, lpread);
649 assert(This->pStream != NULL);
651 return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
654 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
655 LPVOID lp, LONG size)
657 ICOM_THIS(IAVIStreamImpl,iface);
659 TRACE("(%p,0x%08lx,%p,%ld)\n", iface, fcc, lp, size);
661 assert(This->pStream != NULL);
663 return IAVIStream_WriteData(This->pStream, fcc, lp, size);
666 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
667 LPAVISTREAMINFOW info, LONG infolen)
669 FIXME("(%p,%p,%ld): stub\n", iface, info, infolen);
674 /***********************************************************************/
676 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
681 assert(This != NULL);
682 assert(This->pStream != NULL);
684 if (This->has != NULL)
687 if (This->lpInFormat == NULL) {
688 /* decode or encode the data from pStream */
689 hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
692 This->lpInFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GMEM_MOVEABLE, This->cbInFormat);
693 if (This->lpInFormat == NULL)
694 return AVIERR_MEMORY;
696 hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
697 This->lpInFormat, &This->cbInFormat);
701 if (This->lpOutFormat == NULL) {
702 /* we must decode to default format */
703 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
704 This->lpOutFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, This->cbOutFormat);
705 if (This->lpOutFormat == NULL)
706 return AVIERR_MEMORY;
708 This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
709 if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
710 This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
711 return AVIERR_NOCOMPRESSOR;
713 } else if (This->lpOutFormat == NULL)
714 return AVIERR_ERROR; /* To what should I encode? */
716 if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
717 NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
718 return AVIERR_NOCOMPRESSOR;
720 /* update AVISTREAMINFO structure */
721 This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
722 This->sInfo.dwScale = This->lpOutFormat->nBlockAlign;
723 This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec;
724 This->sInfo.dwQuality = ICQUALITY_DEFAULT;
725 SetRectEmpty(&This->sInfo.rcFrame);
727 /* convert positions ansd sizes to output format */
728 CONVERT_STREAM_to_THIS(This->sInfo.dwStart);
729 CONVERT_STREAM_to_THIS(This->sInfo.dwLength);
730 CONVERT_STREAM_to_THIS(This->sInfo.dwSuggestedBufferSize);