ole32: Create moniker enumerator with an initial reference count.
[wine/multimedia.git] / dlls / avifil32 / acmstream.c
blob067f34aeccb1c0b298a4ce2ffe22dc7ed789edb0
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 "mmsystem.h"
30 #include "vfw.h"
31 #include "msacm.h"
33 #include "avifile_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
39 /***********************************************************************/
41 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
42 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream*iface);
43 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface);
44 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
45 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
46 static LONG WINAPI ACMStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
47 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
48 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
49 static HRESULT WINAPI ACMStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
50 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
51 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
52 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
53 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
54 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
56 static const struct IAVIStreamVtbl iacmst = {
57 ACMStream_fnQueryInterface,
58 ACMStream_fnAddRef,
59 ACMStream_fnRelease,
60 ACMStream_fnCreate,
61 ACMStream_fnInfo,
62 ACMStream_fnFindSample,
63 ACMStream_fnReadFormat,
64 ACMStream_fnSetFormat,
65 ACMStream_fnRead,
66 ACMStream_fnWrite,
67 ACMStream_fnDelete,
68 ACMStream_fnReadData,
69 ACMStream_fnWriteData,
70 ACMStream_fnSetInfo
73 typedef struct _IAVIStreamImpl {
74 /* IUnknown stuff */
75 const IAVIStreamVtbl *lpVtbl;
76 LONG ref;
78 /* IAVIStream stuff */
79 PAVISTREAM pStream;
80 AVISTREAMINFOW sInfo;
82 HACMSTREAM has;
84 LPWAVEFORMATEX lpInFormat;
85 LONG cbInFormat;
87 LPWAVEFORMATEX lpOutFormat;
88 LONG cbOutFormat;
90 ACMSTREAMHEADER acmStreamHdr;
91 } IAVIStreamImpl;
93 /***********************************************************************/
95 #define CONVERT_STREAM_to_THIS(a) do { \
96 DWORD __bytes; \
97 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
98 &__bytes, ACM_STREAMSIZEF_SOURCE); \
99 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
101 #define CONVERT_THIS_to_STREAM(a) do { \
102 DWORD __bytes; \
103 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
104 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
105 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
107 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This);
109 HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppv)
111 IAVIStreamImpl *pstream;
112 HRESULT hr;
114 assert(riid != NULL && ppv != NULL);
116 *ppv = NULL;
118 pstream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAVIStreamImpl));
119 if (pstream == NULL)
120 return AVIERR_MEMORY;
122 pstream->lpVtbl = &iacmst;
124 hr = IAVIStream_QueryInterface((IAVIStream*)pstream, riid, ppv);
125 if (FAILED(hr))
126 HeapFree(GetProcessHeap(), 0, pstream);
128 return hr;
131 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
132 REFIID refiid, LPVOID *obj)
134 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
136 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
138 if (IsEqualGUID(&IID_IUnknown, refiid) ||
139 IsEqualGUID(&IID_IAVIStream, refiid)) {
140 *obj = This;
141 IAVIStream_AddRef(iface);
143 return S_OK;
146 return OLE_E_ENUM_NOMORE;
149 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface)
151 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
152 ULONG ref = InterlockedIncrement(&This->ref);
154 TRACE("(%p) -> %ld\n", iface, ref);
156 /* also add reference to the nested stream */
157 if (This->pStream != NULL)
158 IAVIStream_AddRef(This->pStream);
160 return ref;
163 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
165 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
166 ULONG ref = InterlockedDecrement(&This->ref);
168 TRACE("(%p) -> %ld\n", iface, ref);
170 if (ref == 0) {
171 /* destruct */
172 if (This->has != NULL) {
173 if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
174 acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
175 acmStreamClose(This->has, 0);
176 This->has = NULL;
178 if (This->acmStreamHdr.pbSrc != NULL) {
179 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
180 This->acmStreamHdr.pbSrc = NULL;
182 if (This->acmStreamHdr.pbDst != NULL) {
183 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
184 This->acmStreamHdr.pbDst = NULL;
186 if (This->lpInFormat != NULL) {
187 HeapFree(GetProcessHeap(), 0, This->lpInFormat);
188 This->lpInFormat = NULL;
189 This->cbInFormat = 0;
191 if (This->lpOutFormat != NULL) {
192 HeapFree(GetProcessHeap(), 0, This->lpOutFormat);
193 This->lpOutFormat = NULL;
194 This->cbOutFormat = 0;
196 if (This->pStream != NULL) {
197 IAVIStream_Release(This->pStream);
198 This->pStream = NULL;
200 HeapFree(GetProcessHeap(), 0, This);
202 return 0;
205 /* also release reference to the nested stream */
206 if (This->pStream != NULL)
207 IAVIStream_Release(This->pStream);
209 return ref;
212 /* lParam1: PAVISTREAM
213 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
215 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
216 LPARAM lParam2)
218 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
220 TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
222 /* check for swapped parameters */
223 if ((LPVOID)lParam1 != NULL &&
224 ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
225 register LPARAM tmp = lParam1;
227 lParam1 = lParam2;
228 lParam2 = tmp;
231 if ((LPVOID)lParam1 == NULL)
232 return AVIERR_BADPARAM;
234 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
235 if (This->sInfo.fccType != streamtypeAUDIO)
236 return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
238 This->sInfo.fccHandler = 0; /* be paranoid */
240 /* FIXME: check ACM version? Which version does we need? */
242 if ((LPVOID)lParam2 != NULL) {
243 /* We only need the format from the compress-options */
244 if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
245 lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
247 if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
248 This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
249 else
250 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
252 This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
253 if (This->lpOutFormat == NULL)
254 return AVIERR_MEMORY;
256 memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
257 } else {
258 This->lpOutFormat = NULL;
259 This->cbOutFormat = 0;
262 This->pStream = (PAVISTREAM)lParam1;
263 IAVIStream_AddRef(This->pStream);
265 return AVIERR_OK;
268 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
269 LONG size)
271 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
273 TRACE("(%p,%p,%ld)\n", iface, psi, size);
275 if (psi == NULL)
276 return AVIERR_BADPARAM;
277 if (size < 0)
278 return AVIERR_BADSIZE;
280 /* Need codec to correct some values in structure */
281 if (This->has == NULL) {
282 HRESULT hr = AVIFILE_OpenCompressor(This);
284 if (FAILED(hr))
285 return hr;
288 memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
290 if (size < (LONG)sizeof(This->sInfo))
291 return AVIERR_BUFFERTOOSMALL;
292 return AVIERR_OK;
295 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
296 LONG flags)
298 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
300 TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
302 if (flags & FIND_FROM_START) {
303 pos = This->sInfo.dwStart;
304 flags &= ~(FIND_FROM_START|FIND_PREV);
305 flags |= FIND_NEXT;
308 /* convert pos from our 'space' to This->pStream's one */
309 CONVERT_THIS_to_STREAM(&pos);
311 /* ask stream */
312 pos = IAVIStream_FindSample(This->pStream, pos, flags);
314 if (pos != -1) {
315 /* convert pos back to our 'space' if it's no size or physical pos */
316 if ((flags & FIND_RET) == 0)
317 CONVERT_STREAM_to_THIS(&pos);
320 return pos;
323 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
324 LPVOID format, LONG *formatsize)
326 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
328 TRACE("(%p,%ld,%p,%p)\n", iface, pos, format, formatsize);
330 if (formatsize == NULL)
331 return AVIERR_BADPARAM;
333 if (This->has == NULL) {
334 HRESULT hr = AVIFILE_OpenCompressor(This);
336 if (FAILED(hr))
337 return hr;
340 /* only interested in needed buffersize? */
341 if (format == NULL || *formatsize <= 0) {
342 *formatsize = This->cbOutFormat;
344 return AVIERR_OK;
347 /* copy initial format (only as much as will fit) */
348 memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
349 if (*formatsize < This->cbOutFormat) {
350 *formatsize = This->cbOutFormat;
351 return AVIERR_BUFFERTOOSMALL;
354 *formatsize = This->cbOutFormat;
355 return AVIERR_OK;
358 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
359 LPVOID format, LONG formatsize)
361 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
363 HRESULT hr;
365 TRACE("(%p,%ld,%p,%ld)\n", iface, pos, format, formatsize);
367 /* check parameters */
368 if (format == NULL || formatsize <= 0)
369 return AVIERR_BADPARAM;
371 /* Input format already known?
372 * Changing is unsupported, but be quiet if it's the same */
373 if (This->lpInFormat != NULL) {
374 if (This->cbInFormat != formatsize ||
375 memcmp(format, This->lpInFormat, formatsize) != 0)
376 return AVIERR_UNSUPPORTED;
378 return AVIERR_OK;
381 /* Does the nested stream support writing? */
382 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
383 return AVIERR_READONLY;
385 This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, formatsize);
386 if (This->lpInFormat == NULL)
387 return AVIERR_MEMORY;
388 This->cbInFormat = formatsize;
389 memcpy(This->lpInFormat, format, formatsize);
391 /* initialize formats and get compressor */
392 hr = AVIFILE_OpenCompressor(This);
393 if (FAILED(hr))
394 return hr;
396 CONVERT_THIS_to_STREAM(&pos);
398 /* tell the nested stream the new format */
399 return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
400 This->cbOutFormat);
403 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
404 LONG samples, LPVOID buffer,
405 LONG buffersize, LPLONG bytesread,
406 LPLONG samplesread)
408 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
410 HRESULT hr;
411 DWORD size;
413 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", iface, start, samples, buffer,
414 buffersize, bytesread, samplesread);
416 /* clear return parameters if given */
417 if (bytesread != NULL)
418 *bytesread = 0;
419 if (samplesread != NULL)
420 *samplesread = 0;
422 /* Do we have our compressor? */
423 if (This->has == NULL) {
424 hr = AVIFILE_OpenCompressor(This);
426 if (FAILED(hr))
427 return hr;
430 /* only need to pass through? */
431 if (This->cbInFormat == This->cbOutFormat &&
432 memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
433 return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
434 bytesread, samplesread);
437 /* read as much as fit? */
438 if (samples == -1)
439 samples = buffersize / This->lpOutFormat->nBlockAlign;
440 /* limit to buffersize */
441 if (samples * This->lpOutFormat->nBlockAlign > buffersize)
442 samples = buffersize / This->lpOutFormat->nBlockAlign;
444 /* only return needed size? */
445 if (buffer == NULL || buffersize <= 0 || samples == 0) {
446 if (bytesread == NULL && samplesread == NULL)
447 return AVIERR_BADPARAM;
449 if (bytesread != NULL)
450 *bytesread = samples * This->lpOutFormat->nBlockAlign;
451 if (samplesread != NULL)
452 *samplesread = samples;
454 return AVIERR_OK;
457 /* map our positions to pStream positions */
458 CONVERT_THIS_to_STREAM(&start);
460 /* our needed internal buffersize */
461 size = samples * This->lpInFormat->nBlockAlign;
463 /* Need to free destination buffer used for writing? */
464 if (This->acmStreamHdr.pbDst != NULL) {
465 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
466 This->acmStreamHdr.pbDst = NULL;
467 This->acmStreamHdr.dwDstUser = 0;
470 /* need bigger source buffer? */
471 if (This->acmStreamHdr.pbSrc == NULL ||
472 This->acmStreamHdr.dwSrcUser < size) {
473 if (This->acmStreamHdr.pbSrc == NULL)
474 This->acmStreamHdr.pbSrc = HeapAlloc(GetProcessHeap(), 0, size);
475 else
476 This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc, size);
477 if (This->acmStreamHdr.pbSrc == NULL)
478 return AVIERR_MEMORY;
479 This->acmStreamHdr.dwSrcUser = size;
482 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
483 This->acmStreamHdr.cbSrcLengthUsed = 0;
484 This->acmStreamHdr.cbDstLengthUsed = 0;
485 This->acmStreamHdr.cbSrcLength = size;
487 /* read source data */
488 hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
489 This->acmStreamHdr.cbSrcLength,
490 (LONG *)&This->acmStreamHdr.cbSrcLength, NULL);
491 if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
492 return hr;
494 /* need to prepare stream? */
495 This->acmStreamHdr.pbDst = buffer;
496 This->acmStreamHdr.cbDstLength = buffersize;
497 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
498 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
499 This->acmStreamHdr.pbDst = NULL;
500 This->acmStreamHdr.cbDstLength = 0;
501 return AVIERR_COMPRESSOR;
505 /* now do the conversion */
506 /* FIXME: use ACM_CONVERTF_* flags */
507 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
508 hr = AVIERR_COMPRESSOR;
510 This->acmStreamHdr.pbDst = NULL;
511 This->acmStreamHdr.cbDstLength = 0;
513 /* fill out return parameters if given */
514 if (bytesread != NULL)
515 *bytesread = This->acmStreamHdr.cbDstLengthUsed;
516 if (samplesread != NULL)
517 *samplesread =
518 This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
520 return hr;
523 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
524 LONG samples, LPVOID buffer,
525 LONG buffersize, DWORD flags,
526 LPLONG sampwritten,
527 LPLONG byteswritten)
529 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
531 HRESULT hr;
532 ULONG size;
534 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n", iface, start, samples,
535 buffer, buffersize, flags, sampwritten, byteswritten);
537 /* clear return parameters if given */
538 if (sampwritten != NULL)
539 *sampwritten = 0;
540 if (byteswritten != NULL)
541 *byteswritten = 0;
543 /* check parameters */
544 if (buffer == NULL && (buffersize > 0 || samples > 0))
545 return AVIERR_BADPARAM;
547 /* Have we write capability? */
548 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
549 return AVIERR_READONLY;
551 /* also need a compressor */
552 if (This->has == NULL)
553 return AVIERR_NOCOMPRESSOR;
555 /* map our sizes to pStream sizes */
556 size = buffersize;
557 CONVERT_THIS_to_STREAM(&size);
558 CONVERT_THIS_to_STREAM(&start);
560 /* no bytes to write? -- short circuit */
561 if (size == 0) {
562 return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
563 flags, sampwritten, byteswritten);
566 /* Need to free source buffer used for reading? */
567 if (This->acmStreamHdr.pbSrc != NULL) {
568 HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
569 This->acmStreamHdr.pbSrc = NULL;
570 This->acmStreamHdr.dwSrcUser = 0;
573 /* Need bigger destination buffer? */
574 if (This->acmStreamHdr.pbDst == NULL ||
575 This->acmStreamHdr.dwDstUser < size) {
576 if (This->acmStreamHdr.pbDst == NULL)
577 This->acmStreamHdr.pbDst = HeapAlloc(GetProcessHeap(), 0, size);
578 else
579 This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbDst, size);
580 if (This->acmStreamHdr.pbDst == NULL)
581 return AVIERR_MEMORY;
582 This->acmStreamHdr.dwDstUser = size;
584 This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
585 This->acmStreamHdr.cbSrcLengthUsed = 0;
586 This->acmStreamHdr.cbDstLengthUsed = 0;
587 This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser;
589 /* need to prepare stream? */
590 This->acmStreamHdr.pbSrc = buffer;
591 This->acmStreamHdr.cbSrcLength = buffersize;
592 if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
593 if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
594 This->acmStreamHdr.pbSrc = NULL;
595 This->acmStreamHdr.cbSrcLength = 0;
596 return AVIERR_COMPRESSOR;
600 /* now do the conversion */
601 /* FIXME: use ACM_CONVERTF_* flags */
602 if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
603 hr = AVIERR_COMPRESSOR;
604 else
605 hr = AVIERR_OK;
607 This->acmStreamHdr.pbSrc = NULL;
608 This->acmStreamHdr.cbSrcLength = 0;
610 if (FAILED(hr))
611 return hr;
613 return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
614 This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
615 This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
616 byteswritten);
619 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
620 LONG samples)
622 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
624 TRACE("(%p,%ld,%ld)\n", iface, start, samples);
626 /* check parameters */
627 if (start < 0 || samples < 0)
628 return AVIERR_BADPARAM;
630 /* Delete before start of stream? */
631 if ((DWORD)(start + samples) < This->sInfo.dwStart)
632 return AVIERR_OK;
634 /* Delete after end of stream? */
635 if ((DWORD)start > This->sInfo.dwLength)
636 return AVIERR_OK;
638 /* For the rest we need write capability */
639 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
640 return AVIERR_READONLY;
642 /* A compressor is also necessary */
643 if (This->has == NULL)
644 return AVIERR_NOCOMPRESSOR;
646 /* map our positions to pStream positions */
647 CONVERT_THIS_to_STREAM(&start);
648 CONVERT_THIS_to_STREAM(&samples);
650 return IAVIStream_Delete(This->pStream, start, samples);
653 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
654 LPVOID lp, LPLONG lpread)
656 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
658 TRACE("(%p,0x%08lX,%p,%p)\n", iface, fcc, lp, lpread);
660 assert(This->pStream != NULL);
662 return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
665 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
666 LPVOID lp, LONG size)
668 IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
670 TRACE("(%p,0x%08lx,%p,%ld)\n", iface, fcc, lp, size);
672 assert(This->pStream != NULL);
674 return IAVIStream_WriteData(This->pStream, fcc, lp, size);
677 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
678 LPAVISTREAMINFOW info, LONG infolen)
680 FIXME("(%p,%p,%ld): stub\n", iface, info, infolen);
682 return E_FAIL;
685 /***********************************************************************/
687 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
689 HRESULT hr;
691 /* pre-conditions */
692 assert(This != NULL);
693 assert(This->pStream != NULL);
695 if (This->has != NULL)
696 return AVIERR_OK;
698 if (This->lpInFormat == NULL) {
699 /* decode or encode the data from pStream */
700 hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
701 if (FAILED(hr))
702 return hr;
703 This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat);
704 if (This->lpInFormat == NULL)
705 return AVIERR_MEMORY;
707 hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
708 This->lpInFormat, &This->cbInFormat);
709 if (FAILED(hr))
710 return hr;
712 if (This->lpOutFormat == NULL) {
713 /* we must decode to default format */
714 This->cbOutFormat = sizeof(PCMWAVEFORMAT);
715 This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
716 if (This->lpOutFormat == NULL)
717 return AVIERR_MEMORY;
719 This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
720 if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
721 This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
722 return AVIERR_NOCOMPRESSOR;
724 } else if (This->lpOutFormat == NULL)
725 return AVIERR_ERROR; /* To what should I encode? */
727 if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
728 NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
729 return AVIERR_NOCOMPRESSOR;
731 /* update AVISTREAMINFO structure */
732 This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
733 This->sInfo.dwScale = This->lpOutFormat->nBlockAlign;
734 This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec;
735 This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT;
736 SetRectEmpty(&This->sInfo.rcFrame);
738 /* convert positions ansd sizes to output format */
739 CONVERT_STREAM_to_THIS(&This->sInfo.dwStart);
740 CONVERT_STREAM_to_THIS(&This->sInfo.dwLength);
741 CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize);
743 return AVIERR_OK;