d3d8: Render state additions.
[wine/multimedia.git] / dlls / avifil32 / acmstream.c
blob0dc068f195e7164eed2bb56abb432ea54cac26bd
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 static const struct IAVIStreamVtbl iacmst = {
58 ACMStream_fnQueryInterface,
59 ACMStream_fnAddRef,
60 ACMStream_fnRelease,
61 ACMStream_fnCreate,
62 ACMStream_fnInfo,
63 ACMStream_fnFindSample,
64 ACMStream_fnReadFormat,
65 ACMStream_fnSetFormat,
66 ACMStream_fnRead,
67 ACMStream_fnWrite,
68 ACMStream_fnDelete,
69 ACMStream_fnReadData,
70 ACMStream_fnWriteData,
71 ACMStream_fnSetInfo
74 typedef struct _IAVIStreamImpl {
75 /* IUnknown stuff */
76 const IAVIStreamVtbl *lpVtbl;
77 LONG ref;
79 /* IAVIStream stuff */
80 PAVISTREAM pStream;
81 AVISTREAMINFOW sInfo;
83 HACMSTREAM has;
85 LPWAVEFORMATEX lpInFormat;
86 LONG cbInFormat;
88 LPWAVEFORMATEX lpOutFormat;
89 LONG cbOutFormat;
91 ACMSTREAMHEADER acmStreamHdr;
92 } IAVIStreamImpl;
94 /***********************************************************************/
96 #define CONVERT_STREAM_to_THIS(a) do { \
97 DWORD __bytes; \
98 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
99 &__bytes, ACM_STREAMSIZEF_SOURCE); \
100 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
102 #define CONVERT_THIS_to_STREAM(a) do { \
103 DWORD __bytes; \
104 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
105 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
106 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
108 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This);
110 HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppv)
112 IAVIStreamImpl *pstream;
113 HRESULT hr;
115 assert(riid != NULL && ppv != NULL);
117 *ppv = NULL;
119 pstream = (IAVIStreamImpl*)LocalAlloc(LPTR, sizeof(IAVIStreamImpl));
120 if (pstream == NULL)
121 return AVIERR_MEMORY;
123 pstream->lpVtbl = &iacmst;
125 hr = IAVIStream_QueryInterface((IAVIStream*)pstream, riid, ppv);
126 if (FAILED(hr))
127 LocalFree((HLOCAL)pstream);
129 return hr;
132 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
133 REFIID refiid, LPVOID *obj)
135 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
137 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
139 if (IsEqualGUID(&IID_IUnknown, refiid) ||
140 IsEqualGUID(&IID_IAVIStream, refiid)) {
141 *obj = This;
142 IAVIStream_AddRef(iface);
144 return S_OK;
147 return OLE_E_ENUM_NOMORE;
150 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface)
152 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
153 ULONG ref = InterlockedIncrement(&This->ref);
155 TRACE("(%p) -> %ld\n", iface, ref);
157 /* also add reference to the nested stream */
158 if (This->pStream != NULL)
159 IAVIStream_AddRef(This->pStream);
161 return ref;
164 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
166 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
167 ULONG ref = InterlockedDecrement(&This->ref);
169 TRACE("(%p) -> %ld\n", iface, ref);
171 if (ref == 0) {
172 /* destruct */
173 if (This->has != NULL) {
174 if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
175 acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
176 acmStreamClose(This->has, 0);
177 This->has = NULL;
179 if (This->acmStreamHdr.pbSrc != NULL) {
180 GlobalFreePtr(This->acmStreamHdr.pbSrc);
181 This->acmStreamHdr.pbSrc = NULL;
183 if (This->acmStreamHdr.pbDst != NULL) {
184 GlobalFreePtr(This->acmStreamHdr.pbDst);
185 This->acmStreamHdr.pbDst = NULL;
187 if (This->lpInFormat != NULL) {
188 GlobalFreePtr(This->lpInFormat);
189 This->lpInFormat = NULL;
190 This->cbInFormat = 0;
192 if (This->lpOutFormat != NULL) {
193 GlobalFreePtr(This->lpOutFormat);
194 This->lpOutFormat = NULL;
195 This->cbOutFormat = 0;
197 if (This->pStream != NULL) {
198 IAVIStream_Release(This->pStream);
199 This->pStream = NULL;
201 LocalFree((HLOCAL)This);
203 return 0;
206 /* also release reference to the nested stream */
207 if (This->pStream != NULL)
208 IAVIStream_Release(This->pStream);
210 return ref;
213 /* lParam1: PAVISTREAM
214 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
216 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
217 LPARAM lParam2)
219 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
221 TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
223 /* check for swapped parameters */
224 if ((LPVOID)lParam1 != NULL &&
225 ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
226 register LPARAM tmp = lParam1;
228 lParam1 = lParam2;
229 lParam2 = tmp;
232 if ((LPVOID)lParam1 == NULL)
233 return AVIERR_BADPARAM;
235 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
236 if (This->sInfo.fccType != streamtypeAUDIO)
237 return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
239 This->sInfo.fccHandler = 0; /* be paranoid */
241 /* FIXME: check ACM version? Which version does we need? */
243 if ((LPVOID)lParam2 != NULL) {
244 /* We only need the format from the compress-options */
245 if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
246 lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
248 if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
249 This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
250 else
251 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
253 This->lpOutFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, This->cbOutFormat);
254 if (This->lpOutFormat == NULL)
255 return AVIERR_MEMORY;
257 memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
258 } else {
259 This->lpOutFormat = NULL;
260 This->cbOutFormat = 0;
263 This->pStream = (PAVISTREAM)lParam1;
264 IAVIStream_AddRef(This->pStream);
266 return AVIERR_OK;
269 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
270 LONG size)
272 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
274 TRACE("(%p,%p,%ld)\n", iface, psi, size);
276 if (psi == NULL)
277 return AVIERR_BADPARAM;
278 if (size < 0)
279 return AVIERR_BADSIZE;
281 /* Need codec to correct some values in structure */
282 if (This->has == NULL) {
283 HRESULT hr = AVIFILE_OpenCompressor(This);
285 if (FAILED(hr))
286 return hr;
289 memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
291 if (size < (LONG)sizeof(This->sInfo))
292 return AVIERR_BUFFERTOOSMALL;
293 return AVIERR_OK;
296 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
297 LONG flags)
299 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
301 TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
303 if (flags & FIND_FROM_START) {
304 pos = This->sInfo.dwStart;
305 flags &= ~(FIND_FROM_START|FIND_PREV);
306 flags |= FIND_NEXT;
309 /* convert pos from our 'space' to This->pStream's one */
310 CONVERT_THIS_to_STREAM(&pos);
312 /* ask stream */
313 pos = IAVIStream_FindSample(This->pStream, pos, flags);
315 if (pos != -1) {
316 /* convert pos back to our 'space' if it's no size or physical pos */
317 if ((flags & FIND_RET) == 0)
318 CONVERT_STREAM_to_THIS(&pos);
321 return pos;
324 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
325 LPVOID format, LONG *formatsize)
327 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
329 TRACE("(%p,%ld,%p,%p)\n", iface, pos, format, formatsize);
331 if (formatsize == NULL)
332 return AVIERR_BADPARAM;
334 if (This->has == NULL) {
335 HRESULT hr = AVIFILE_OpenCompressor(This);
337 if (FAILED(hr))
338 return hr;
341 /* only interested in needed buffersize? */
342 if (format == NULL || *formatsize <= 0) {
343 *formatsize = This->cbOutFormat;
345 return AVIERR_OK;
348 /* copy initial format (only as much as will fit) */
349 memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
350 if (*formatsize < This->cbOutFormat) {
351 *formatsize = This->cbOutFormat;
352 return AVIERR_BUFFERTOOSMALL;
355 *formatsize = This->cbOutFormat;
356 return AVIERR_OK;
359 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
360 LPVOID format, LONG formatsize)
362 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
364 HRESULT hr;
366 TRACE("(%p,%ld,%p,%ld)\n", iface, pos, format, formatsize);
368 /* check parameters */
369 if (format == NULL || formatsize <= 0)
370 return AVIERR_BADPARAM;
372 /* Input format already known?
373 * Changing is unsupported, but be quiet if it's the same */
374 if (This->lpInFormat != NULL) {
375 if (This->cbInFormat != formatsize ||
376 memcmp(format, This->lpInFormat, formatsize) != 0)
377 return AVIERR_UNSUPPORTED;
379 return AVIERR_OK;
382 /* Does the nested stream support writing? */
383 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
384 return AVIERR_READONLY;
386 This->lpInFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GMEM_MOVEABLE, formatsize);
387 if (This->lpInFormat == NULL)
388 return AVIERR_MEMORY;
389 This->cbInFormat = formatsize;
390 memcpy(This->lpInFormat, format, formatsize);
392 /* initialize formats and get compressor */
393 hr = AVIFILE_OpenCompressor(This);
394 if (FAILED(hr))
395 return hr;
397 CONVERT_THIS_to_STREAM(&pos);
399 /* tell the nested stream the new format */
400 return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
401 This->cbOutFormat);
404 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
405 LONG samples, LPVOID buffer,
406 LONG buffersize, LPLONG bytesread,
407 LPLONG samplesread)
409 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
411 HRESULT hr;
412 DWORD size;
414 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", iface, start, samples, buffer,
415 buffersize, bytesread, samplesread);
417 /* clear return parameters if given */
418 if (bytesread != NULL)
419 *bytesread = 0;
420 if (samplesread != NULL)
421 *samplesread = 0;
423 /* Do we have our compressor? */
424 if (This->has == NULL) {
425 hr = AVIFILE_OpenCompressor(This);
427 if (FAILED(hr))
428 return hr;
431 /* only need to pass through? */
432 if (This->cbInFormat == This->cbOutFormat &&
433 memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
434 return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
435 bytesread, samplesread);
438 /* read as much as fit? */
439 if (samples == -1)
440 samples = buffersize / This->lpOutFormat->nBlockAlign;
441 /* limit to buffersize */
442 if (samples * This->lpOutFormat->nBlockAlign > buffersize)
443 samples = buffersize / This->lpOutFormat->nBlockAlign;
445 /* only return needed size? */
446 if (buffer == NULL || buffersize <= 0 || samples == 0) {
447 if (bytesread == NULL && samplesread == NULL)
448 return AVIERR_BADPARAM;
450 if (bytesread != NULL)
451 *bytesread = samples * This->lpOutFormat->nBlockAlign;
452 if (samplesread != NULL)
453 *samplesread = samples;
455 return AVIERR_OK;
458 /* map our positions to pStream positions */
459 CONVERT_THIS_to_STREAM(&start);
461 /* our needed internal buffersize */
462 size = samples * This->lpInFormat->nBlockAlign;
464 /* Need to free destination buffer used for writing? */
465 if (This->acmStreamHdr.pbDst != NULL) {
466 GlobalFreePtr(This->acmStreamHdr.pbDst);
467 This->acmStreamHdr.pbDst = NULL;
468 This->acmStreamHdr.dwDstUser = 0;
471 /* need bigger source buffer? */
472 if (This->acmStreamHdr.pbSrc == NULL ||
473 This->acmStreamHdr.dwSrcUser < size) {
474 if (This->acmStreamHdr.pbSrc == NULL)
475 This->acmStreamHdr.pbSrc = GlobalAllocPtr(GMEM_MOVEABLE, size);
476 else
477 This->acmStreamHdr.pbSrc = GlobalReAllocPtr(This->acmStreamHdr.pbSrc,
478 size, GMEM_MOVEABLE);
479 if (This->acmStreamHdr.pbSrc == NULL)
480 return AVIERR_MEMORY;
481 This->acmStreamHdr.dwSrcUser = size;
484 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
485 This->acmStreamHdr.cbSrcLengthUsed = 0;
486 This->acmStreamHdr.cbDstLengthUsed = 0;
487 This->acmStreamHdr.cbSrcLength = size;
489 /* read source data */
490 hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
491 This->acmStreamHdr.cbSrcLength,
492 (LONG *)&This->acmStreamHdr.cbSrcLength, NULL);
493 if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
494 return hr;
496 /* need to prepare stream? */
497 This->acmStreamHdr.pbDst = buffer;
498 This->acmStreamHdr.cbDstLength = buffersize;
499 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
500 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
501 This->acmStreamHdr.pbDst = NULL;
502 This->acmStreamHdr.cbDstLength = 0;
503 return AVIERR_COMPRESSOR;
507 /* now do the conversion */
508 /* FIXME: use ACM_CONVERTF_* flags */
509 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
510 hr = AVIERR_COMPRESSOR;
512 This->acmStreamHdr.pbDst = NULL;
513 This->acmStreamHdr.cbDstLength = 0;
515 /* fill out return parameters if given */
516 if (bytesread != NULL)
517 *bytesread = This->acmStreamHdr.cbDstLengthUsed;
518 if (samplesread != NULL)
519 *samplesread =
520 This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
522 return hr;
525 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
526 LONG samples, LPVOID buffer,
527 LONG buffersize, DWORD flags,
528 LPLONG sampwritten,
529 LPLONG byteswritten)
531 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
533 HRESULT hr;
534 ULONG size;
536 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n", iface, start, samples,
537 buffer, buffersize, flags, sampwritten, byteswritten);
539 /* clear return parameters if given */
540 if (sampwritten != NULL)
541 *sampwritten = 0;
542 if (byteswritten != NULL)
543 *byteswritten = 0;
545 /* check parameters */
546 if (buffer == NULL && (buffersize > 0 || samples > 0))
547 return AVIERR_BADPARAM;
549 /* Have we write capability? */
550 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
551 return AVIERR_READONLY;
553 /* also need a compressor */
554 if (This->has == NULL)
555 return AVIERR_NOCOMPRESSOR;
557 /* map our sizes to pStream sizes */
558 size = buffersize;
559 CONVERT_THIS_to_STREAM(&size);
560 CONVERT_THIS_to_STREAM(&start);
562 /* no bytes to write? -- short circuit */
563 if (size == 0) {
564 return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
565 flags, sampwritten, byteswritten);
568 /* Need to free source buffer used for reading? */
569 if (This->acmStreamHdr.pbSrc != NULL) {
570 GlobalFreePtr(This->acmStreamHdr.pbSrc);
571 This->acmStreamHdr.pbSrc = NULL;
572 This->acmStreamHdr.dwSrcUser = 0;
575 /* Need bigger destination buffer? */
576 if (This->acmStreamHdr.pbDst == NULL ||
577 This->acmStreamHdr.dwDstUser < size) {
578 if (This->acmStreamHdr.pbDst == NULL)
579 This->acmStreamHdr.pbDst = GlobalAllocPtr(GMEM_MOVEABLE, size);
580 else
581 This->acmStreamHdr.pbDst = GlobalReAllocPtr(This->acmStreamHdr.pbDst,
582 size, GMEM_MOVEABLE);
583 if (This->acmStreamHdr.pbDst == NULL)
584 return AVIERR_MEMORY;
585 This->acmStreamHdr.dwDstUser = size;
587 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
588 This->acmStreamHdr.cbSrcLengthUsed = 0;
589 This->acmStreamHdr.cbDstLengthUsed = 0;
590 This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser;
592 /* need to prepare stream? */
593 This->acmStreamHdr.pbSrc = buffer;
594 This->acmStreamHdr.cbSrcLength = buffersize;
595 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
596 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
597 This->acmStreamHdr.pbSrc = NULL;
598 This->acmStreamHdr.cbSrcLength = 0;
599 return AVIERR_COMPRESSOR;
603 /* now do the conversion */
604 /* FIXME: use ACM_CONVERTF_* flags */
605 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
606 hr = AVIERR_COMPRESSOR;
607 else
608 hr = AVIERR_OK;
610 This->acmStreamHdr.pbSrc = NULL;
611 This->acmStreamHdr.cbSrcLength = 0;
613 if (FAILED(hr))
614 return hr;
616 return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
617 This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
618 This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
619 byteswritten);
622 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
623 LONG samples)
625 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
627 TRACE("(%p,%ld,%ld)\n", iface, start, samples);
629 /* check parameters */
630 if (start < 0 || samples < 0)
631 return AVIERR_BADPARAM;
633 /* Delete before start of stream? */
634 if ((DWORD)(start + samples) < This->sInfo.dwStart)
635 return AVIERR_OK;
637 /* Delete after end of stream? */
638 if ((DWORD)start > This->sInfo.dwLength)
639 return AVIERR_OK;
641 /* For the rest we need write capability */
642 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
643 return AVIERR_READONLY;
645 /* A compressor is also necessary */
646 if (This->has == NULL)
647 return AVIERR_NOCOMPRESSOR;
649 /* map our positions to pStream positions */
650 CONVERT_THIS_to_STREAM(&start);
651 CONVERT_THIS_to_STREAM(&samples);
653 return IAVIStream_Delete(This->pStream, start, samples);
656 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
657 LPVOID lp, LPLONG lpread)
659 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
661 TRACE("(%p,0x%08lX,%p,%p)\n", iface, fcc, lp, lpread);
663 assert(This->pStream != NULL);
665 return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
668 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
669 LPVOID lp, LONG size)
671 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
673 TRACE("(%p,0x%08lx,%p,%ld)\n", iface, fcc, lp, size);
675 assert(This->pStream != NULL);
677 return IAVIStream_WriteData(This->pStream, fcc, lp, size);
680 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
681 LPAVISTREAMINFOW info, LONG infolen)
683 FIXME("(%p,%p,%ld): stub\n", iface, info, infolen);
685 return E_FAIL;
688 /***********************************************************************/
690 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
692 HRESULT hr;
694 /* pre-conditions */
695 assert(This != NULL);
696 assert(This->pStream != NULL);
698 if (This->has != NULL)
699 return AVIERR_OK;
701 if (This->lpInFormat == NULL) {
702 /* decode or encode the data from pStream */
703 hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
704 if (FAILED(hr))
705 return hr;
706 This->lpInFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GMEM_MOVEABLE, This->cbInFormat);
707 if (This->lpInFormat == NULL)
708 return AVIERR_MEMORY;
710 hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
711 This->lpInFormat, &This->cbInFormat);
712 if (FAILED(hr))
713 return hr;
715 if (This->lpOutFormat == NULL) {
716 /* we must decode to default format */
717 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
718 This->lpOutFormat = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, This->cbOutFormat);
719 if (This->lpOutFormat == NULL)
720 return AVIERR_MEMORY;
722 This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
723 if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
724 This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
725 return AVIERR_NOCOMPRESSOR;
727 } else if (This->lpOutFormat == NULL)
728 return AVIERR_ERROR; /* To what should I encode? */
730 if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
731 NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
732 return AVIERR_NOCOMPRESSOR;
734 /* update AVISTREAMINFO structure */
735 This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
736 This->sInfo.dwScale = This->lpOutFormat->nBlockAlign;
737 This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec;
738 This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT;
739 SetRectEmpty(&This->sInfo.rcFrame);
741 /* convert positions ansd sizes to output format */
742 CONVERT_STREAM_to_THIS(&This->sInfo.dwStart);
743 CONVERT_STREAM_to_THIS(&This->sInfo.dwLength);
744 CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize);
746 return AVIERR_OK;