dlopen libungif and libjpeg.
[wine.git] / dlls / avifil32 / acmstream.c
blob0c6563bb7751f6849c9aae762f4030a90c37f0d2
1 /*
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
20 #include <assert.h>
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "winerror.h"
29 #include "windowsx.h"
30 #include "mmsystem.h"
31 #include "vfw.h"
32 #include "msacm.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 ICOM_VTABLE(IAVIStream) iacmst = {
58 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
59 ACMStream_fnQueryInterface,
60 ACMStream_fnAddRef,
61 ACMStream_fnRelease,
62 ACMStream_fnCreate,
63 ACMStream_fnInfo,
64 ACMStream_fnFindSample,
65 ACMStream_fnReadFormat,
66 ACMStream_fnSetFormat,
67 ACMStream_fnRead,
68 ACMStream_fnWrite,
69 ACMStream_fnDelete,
70 ACMStream_fnReadData,
71 ACMStream_fnWriteData,
72 ACMStream_fnSetInfo
75 typedef struct _IAVIStreamImpl {
76 /* IUnknown stuff */
77 ICOM_VFIELD(IAVIStream);
78 DWORD ref;
80 /* IAVIStream stuff */
81 PAVISTREAM pStream;
82 AVISTREAMINFOW sInfo;
84 HACMSTREAM has;
86 LPWAVEFORMATEX lpInFormat;
87 LONG cbInFormat;
89 LPWAVEFORMATEX lpOutFormat;
90 LONG cbOutFormat;
92 ACMSTREAMHEADER acmStreamHdr;
93 } IAVIStreamImpl;
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;
111 HRESULT hr;
113 assert(riid != NULL && ppv != NULL);
115 *ppv = NULL;
117 pstream = (IAVIStreamImpl*)LocalAlloc(LPTR, sizeof(IAVIStreamImpl));
118 if (pstream == NULL)
119 return AVIERR_MEMORY;
121 pstream->lpVtbl = &iacmst;
123 hr = IUnknown_QueryInterface((IUnknown*)pstream, riid, ppv);
124 if (FAILED(hr))
125 LocalFree((HLOCAL)pstream);
127 return hr;
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)) {
139 *obj = This;
140 IAVIStream_AddRef(iface);
142 return S_OK;
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) {
168 /* destruct */
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);
173 This->has = NULL;
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);
199 return 0;
202 /* also release reference to the nested stream */
203 if (This->pStream != NULL)
204 IAVIStream_Release(This->pStream);
206 return --This->ref;
209 /* lParam1: PAVISTREAM
210 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
212 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
213 LPARAM lParam2)
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;
224 lParam1 = lParam2;
225 lParam2 = tmp;
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;
246 else
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);
254 } else {
255 This->lpOutFormat = NULL;
256 This->cbOutFormat = 0;
259 This->pStream = (PAVISTREAM)lParam1;
260 IAVIStream_AddRef(This->pStream);
262 return AVIERR_OK;
265 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
266 LONG size)
268 ICOM_THIS(IAVIStreamImpl,iface);
270 TRACE("(%p,%p,%ld)\n", iface, psi, size);
272 if (psi == NULL)
273 return AVIERR_BADPARAM;
274 if (size < 0)
275 return AVIERR_BADSIZE;
277 /* Need codec to correct some values in structure */
278 if (This->has == NULL) {
279 HRESULT hr = AVIFILE_OpenCompressor(This);
281 if (FAILED(hr))
282 return hr;
285 memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
287 if (size < (LONG)sizeof(This->sInfo))
288 return AVIERR_BUFFERTOOSMALL;
289 return AVIERR_OK;
292 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
293 LONG flags)
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);
302 flags |= FIND_NEXT;
305 /* convert pos from our 'space' to This->pStream's one */
306 CONVERT_THIS_to_STREAM(pos);
308 /* ask stream */
309 pos = IAVIStream_FindSample(This->pStream, pos, flags);
311 if (pos != -1) {
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);
317 return 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);
333 if (FAILED(hr))
334 return hr;
337 /* only interested in needed buffersize? */
338 if (format == NULL || *formatsize <= 0) {
339 *formatsize = This->cbOutFormat;
341 return AVIERR_OK;
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;
352 return AVIERR_OK;
355 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
356 LPVOID format, LONG formatsize)
358 ICOM_THIS(IAVIStreamImpl,iface);
360 HRESULT hr;
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;
375 return AVIERR_OK;
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);
390 if (FAILED(hr))
391 return hr;
393 CONVERT_THIS_to_STREAM(pos);
395 /* tell the nested stream the new format */
396 return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
397 This->cbOutFormat);
400 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
401 LONG samples, LPVOID buffer,
402 LONG buffersize, LPLONG bytesread,
403 LPLONG samplesread)
405 ICOM_THIS(IAVIStreamImpl,iface);
407 HRESULT hr;
408 DWORD size;
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)
415 *bytesread = 0;
416 if (samplesread != NULL)
417 *samplesread = 0;
419 /* Do we have our compressor? */
420 if (This->has == NULL) {
421 hr = AVIFILE_OpenCompressor(This);
423 if (FAILED(hr))
424 return hr;
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? */
435 if (samples == -1)
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;
451 return AVIERR_OK;
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);
472 else
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)
490 return hr;
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)
515 *samplesread =
516 This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
518 return hr;
521 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
522 LONG samples, LPVOID buffer,
523 LONG buffersize, DWORD flags,
524 LPLONG sampwritten,
525 LPLONG byteswritten)
527 ICOM_THIS(IAVIStreamImpl,iface);
529 HRESULT hr;
530 LONG size;
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)
537 *sampwritten = 0;
538 if (byteswritten != NULL)
539 *byteswritten = 0;
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 */
554 size = buffersize;
555 CONVERT_THIS_to_STREAM(size);
556 CONVERT_THIS_to_STREAM(start);
558 /* no bytes to write? -- short circuit */
559 if (size == 0) {
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);
576 else
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;
603 else
604 hr = AVIERR_OK;
606 This->acmStreamHdr.pbSrc = NULL;
607 This->acmStreamHdr.cbSrcLength = 0;
609 if (FAILED(hr))
610 return hr;
612 return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
613 This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
614 This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
615 byteswritten);
618 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
619 LONG samples)
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)
631 return AVIERR_OK;
633 /* Delete after end of stream? */
634 if ((DWORD)start > This->sInfo.dwLength)
635 return AVIERR_OK;
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);
681 return E_FAIL;
684 /***********************************************************************/
686 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
688 HRESULT hr;
690 /* pre-conditions */
691 assert(This != NULL);
692 assert(This->pStream != NULL);
694 if (This->has != NULL)
695 return AVIERR_OK;
697 if (This->lpInFormat == NULL) {
698 /* decode or encode the data from pStream */
699 hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
700 if (FAILED(hr))
701 return hr;
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);
708 if (FAILED(hr))
709 return hr;
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);
742 return AVIERR_OK;