~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/avifil32/acmstream.c

Version: ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Copyright 2002 Michael Günnewig
  3  *
  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.
  8  *
  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.
 13  *
 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 17  */
 18 
 19 #include <assert.h>
 20 #include <stdarg.h>
 21 
 22 #include "windef.h"
 23 #include "winbase.h"
 24 #include "wingdi.h"
 25 #include "winuser.h"
 26 #include "winerror.h"
 27 #include "mmsystem.h"
 28 #include "vfw.h"
 29 #include "msacm.h"
 30 
 31 #include "avifile_private.h"
 32 
 33 #include "wine/debug.h"
 34 
 35 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
 36 
 37 /***********************************************************************/
 38 
 39 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
 40 static ULONG   WINAPI ACMStream_fnAddRef(IAVIStream*iface);
 41 static ULONG   WINAPI ACMStream_fnRelease(IAVIStream* iface);
 42 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
 43 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
 44 static LONG    WINAPI ACMStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
 45 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
 46 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
 47 static HRESULT WINAPI ACMStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
 48 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
 49 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
 50 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
 51 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
 52 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
 53 
 54 static const struct IAVIStreamVtbl iacmst = {
 55   ACMStream_fnQueryInterface,
 56   ACMStream_fnAddRef,
 57   ACMStream_fnRelease,
 58   ACMStream_fnCreate,
 59   ACMStream_fnInfo,
 60   ACMStream_fnFindSample,
 61   ACMStream_fnReadFormat,
 62   ACMStream_fnSetFormat,
 63   ACMStream_fnRead,
 64   ACMStream_fnWrite,
 65   ACMStream_fnDelete,
 66   ACMStream_fnReadData,
 67   ACMStream_fnWriteData,
 68   ACMStream_fnSetInfo
 69 };
 70 
 71 typedef struct _IAVIStreamImpl {
 72   /* IUnknown stuff */
 73   const IAVIStreamVtbl *lpVtbl;
 74   LONG            ref;
 75 
 76   /* IAVIStream stuff */
 77   PAVISTREAM      pStream;
 78   AVISTREAMINFOW  sInfo;
 79 
 80   HACMSTREAM      has;
 81 
 82   LPWAVEFORMATEX  lpInFormat;
 83   LONG            cbInFormat;
 84 
 85   LPWAVEFORMATEX  lpOutFormat;
 86   LONG            cbOutFormat;
 87 
 88   ACMSTREAMHEADER acmStreamHdr;
 89 } IAVIStreamImpl;
 90 
 91 /***********************************************************************/
 92 
 93 #define CONVERT_STREAM_to_THIS(a) do { \
 94            DWORD __bytes; \
 95            acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
 96                          &__bytes, ACM_STREAMSIZEF_SOURCE); \
 97            *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
 98 
 99 #define CONVERT_THIS_to_STREAM(a) do { \
100            DWORD __bytes; \
101            acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
102                          &__bytes, ACM_STREAMSIZEF_DESTINATION); \
103            *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
104 
105 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This);
106 
107 HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppv)
108 {
109   IAVIStreamImpl *pstream;
110   HRESULT         hr;
111 
112   assert(riid != NULL && ppv != NULL);
113 
114   *ppv = NULL;
115 
116   pstream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAVIStreamImpl));
117   if (pstream == NULL)
118     return AVIERR_MEMORY;
119 
120   pstream->lpVtbl = &iacmst;
121 
122   hr = IAVIStream_QueryInterface((IAVIStream*)pstream, riid, ppv);
123   if (FAILED(hr))
124     HeapFree(GetProcessHeap(), 0, pstream);
125 
126   return hr;
127 }
128 
129 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
130                                                   REFIID refiid, LPVOID *obj)
131 {
132   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
133 
134   TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
135 
136   if (IsEqualGUID(&IID_IUnknown, refiid) ||
137       IsEqualGUID(&IID_IAVIStream, refiid)) {
138     *obj = This;
139     IAVIStream_AddRef(iface);
140 
141     return S_OK;
142   }
143 
144   return OLE_E_ENUM_NOMORE;
145 }
146 
147 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface)
148 {
149   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
150   ULONG ref = InterlockedIncrement(&This->ref);
151 
152   TRACE("(%p) -> %d\n", iface, ref);
153 
154   /* also add reference to the nested stream */
155   if (This->pStream != NULL)
156     IAVIStream_AddRef(This->pStream);
157 
158   return ref;
159 }
160 
161 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
162 {
163   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
164   ULONG ref = InterlockedDecrement(&This->ref);
165 
166   TRACE("(%p) -> %d\n", iface, ref);
167 
168   if (ref == 0) {
169     /* destruct */
170     if (This->has != NULL) {
171       if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
172         acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
173       acmStreamClose(This->has, 0);
174       This->has = NULL;
175     }
176     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
177     This->acmStreamHdr.pbSrc = NULL;
178     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
179     This->acmStreamHdr.pbDst = NULL;
180     if (This->lpInFormat != NULL) {
181       HeapFree(GetProcessHeap(), 0, This->lpInFormat);
182       This->lpInFormat = NULL;
183       This->cbInFormat = 0;
184     }
185     if (This->lpOutFormat != NULL) {
186       HeapFree(GetProcessHeap(), 0, This->lpOutFormat);
187       This->lpOutFormat = NULL;
188       This->cbOutFormat = 0;
189     }
190     if (This->pStream != NULL) {
191       IAVIStream_Release(This->pStream);
192       This->pStream = NULL;
193     }
194     HeapFree(GetProcessHeap(), 0, This);
195 
196     return 0;
197   }
198 
199   /* also release reference to the nested stream */
200   if (This->pStream != NULL)
201     IAVIStream_Release(This->pStream);
202 
203   return ref;
204 }
205 
206 /* lParam1: PAVISTREAM
207  * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
208  */
209 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
210                                           LPARAM lParam2)
211 {
212   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
213 
214   TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
215 
216   /* check for swapped parameters */
217   if ((LPVOID)lParam1 != NULL &&
218       ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
219     register LPARAM tmp = lParam1;
220 
221     lParam1 = lParam2;
222     lParam2 = tmp;
223   }
224 
225   if ((LPVOID)lParam1 == NULL)
226     return AVIERR_BADPARAM;
227 
228   IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
229   if (This->sInfo.fccType != streamtypeAUDIO)
230     return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
231 
232   This->sInfo.fccHandler = 0; /* be paranoid */
233 
234   /* FIXME: check ACM version? Which version does we need? */
235 
236   if ((LPVOID)lParam2 != NULL) {
237     /* We only need the format from the compress-options */
238     if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
239       lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
240 
241     if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
242       This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
243     else
244       This->cbOutFormat = sizeof(PCMWAVEFORMAT);
245 
246     This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
247     if (This->lpOutFormat == NULL)
248       return AVIERR_MEMORY;
249 
250     memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
251   } else {
252     This->lpOutFormat = NULL;
253     This->cbOutFormat = 0;
254   }
255 
256   This->pStream = (PAVISTREAM)lParam1;
257   IAVIStream_AddRef(This->pStream);
258 
259   return AVIERR_OK;
260 }
261 
262 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
263                                         LONG size)
264 {
265   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
266 
267   TRACE("(%p,%p,%d)\n", iface, psi, size);
268 
269   if (psi == NULL)
270     return AVIERR_BADPARAM;
271   if (size < 0)
272     return AVIERR_BADSIZE;
273 
274   /* Need codec to correct some values in structure */
275   if (This->has == NULL) {
276     HRESULT hr = AVIFILE_OpenCompressor(This);
277 
278     if (FAILED(hr))
279       return hr;
280   }
281 
282   memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
283 
284   if (size < (LONG)sizeof(This->sInfo))
285     return AVIERR_BUFFERTOOSMALL;
286   return AVIERR_OK;
287 }
288 
289 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
290                                            LONG flags)
291 {
292   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
293 
294   TRACE("(%p,%d,0x%08X)\n",iface,pos,flags);
295 
296   if (flags & FIND_FROM_START) {
297     pos = This->sInfo.dwStart;
298     flags &= ~(FIND_FROM_START|FIND_PREV);
299     flags |= FIND_NEXT;
300   }
301 
302   /* convert pos from our 'space' to This->pStream's one */
303   CONVERT_THIS_to_STREAM(&pos);
304 
305   /* ask stream */
306   pos = IAVIStream_FindSample(This->pStream, pos, flags);
307 
308   if (pos != -1) {
309     /* convert pos back to our 'space' if it's no size or physical pos */
310     if ((flags & FIND_RET) == 0)
311       CONVERT_STREAM_to_THIS(&pos);
312   }
313 
314   return pos;
315 }
316 
317 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
318                                               LPVOID format, LONG *formatsize)
319 {
320   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
321 
322   TRACE("(%p,%d,%p,%p)\n", iface, pos, format, formatsize);
323 
324   if (formatsize == NULL)
325     return AVIERR_BADPARAM;
326 
327   if (This->has == NULL) {
328     HRESULT hr = AVIFILE_OpenCompressor(This);
329 
330     if (FAILED(hr))
331       return hr;
332   }
333 
334   /* only interested in needed buffersize? */
335   if (format == NULL || *formatsize <= 0) {
336     *formatsize = This->cbOutFormat;
337 
338     return AVIERR_OK;
339   }
340 
341   /* copy initial format (only as much as will fit) */
342   memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
343   if (*formatsize < This->cbOutFormat) {
344     *formatsize = This->cbOutFormat;
345     return AVIERR_BUFFERTOOSMALL;
346   }
347 
348   *formatsize = This->cbOutFormat;
349   return AVIERR_OK;
350 }
351 
352 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
353                                              LPVOID format, LONG formatsize)
354 {
355   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
356 
357   HRESULT hr;
358 
359   TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);
360 
361   /* check parameters */
362   if (format == NULL || formatsize <= 0)
363     return AVIERR_BADPARAM;
364 
365   /* Input format already known?
366    * Changing is unsupported, but be quiet if it's the same */
367   if (This->lpInFormat != NULL) {
368     if (This->cbInFormat != formatsize ||
369         memcmp(format, This->lpInFormat, formatsize) != 0)
370       return AVIERR_UNSUPPORTED;
371 
372     return AVIERR_OK;
373   }
374 
375   /* Does the nested stream support writing? */
376   if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
377     return AVIERR_READONLY;
378 
379   This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, formatsize);
380   if (This->lpInFormat == NULL)
381     return AVIERR_MEMORY;
382   This->cbInFormat = formatsize;
383   memcpy(This->lpInFormat, format, formatsize);
384 
385   /* initialize formats and get compressor */
386   hr = AVIFILE_OpenCompressor(This);
387   if (FAILED(hr))
388     return hr;
389 
390   CONVERT_THIS_to_STREAM(&pos);
391 
392   /* tell the nested stream the new format */
393   return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
394                               This->cbOutFormat);
395 }
396 
397 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
398                                         LONG samples, LPVOID buffer,
399                                         LONG buffersize, LPLONG bytesread,
400                                         LPLONG samplesread)
401 {
402   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
403 
404   HRESULT hr;
405   DWORD   size;
406 
407   TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer,
408         buffersize, bytesread, samplesread);
409 
410   /* clear return parameters if given */
411   if (bytesread != NULL)
412     *bytesread = 0;
413   if (samplesread != NULL)
414     *samplesread = 0;
415 
416   /* Do we have our compressor? */
417   if (This->has == NULL) {
418     hr = AVIFILE_OpenCompressor(This);
419 
420     if (FAILED(hr))
421       return hr;
422   }
423 
424   /* only need to pass through? */
425   if (This->cbInFormat == This->cbOutFormat &&
426       memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
427     return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
428                            bytesread, samplesread);
429   }
430 
431   /* read as much as fit? */
432   if (samples == -1)
433     samples = buffersize / This->lpOutFormat->nBlockAlign;
434   /* limit to buffersize */
435   if (samples * This->lpOutFormat->nBlockAlign > buffersize)
436     samples = buffersize / This->lpOutFormat->nBlockAlign;
437 
438   /* only return needed size? */
439   if (buffer == NULL || buffersize <= 0 || samples == 0) {
440     if (bytesread == NULL && samplesread == NULL)
441       return AVIERR_BADPARAM;
442 
443     if (bytesread != NULL)
444       *bytesread = samples * This->lpOutFormat->nBlockAlign;
445     if (samplesread != NULL)
446       *samplesread = samples;
447 
448     return AVIERR_OK;
449   }
450 
451   /* map our positions to pStream positions */
452   CONVERT_THIS_to_STREAM(&start);
453 
454   /* our needed internal buffersize */
455   size = samples * This->lpInFormat->nBlockAlign;
456 
457   /* Need to free destination buffer used for writing? */
458   if (This->acmStreamHdr.pbDst != NULL) {
459     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
460     This->acmStreamHdr.pbDst     = NULL;
461     This->acmStreamHdr.dwDstUser = 0;
462   }
463 
464   /* need bigger source buffer? */
465   if (This->acmStreamHdr.pbSrc == NULL ||
466       This->acmStreamHdr.dwSrcUser < size) {
467     if (This->acmStreamHdr.pbSrc == NULL)
468       This->acmStreamHdr.pbSrc = HeapAlloc(GetProcessHeap(), 0, size);
469     else
470       This->acmStreamHdr.pbSrc = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc, size);
471     if (This->acmStreamHdr.pbSrc == NULL)
472       return AVIERR_MEMORY;
473     This->acmStreamHdr.dwSrcUser = size;
474   }
475 
476   This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
477   This->acmStreamHdr.cbSrcLengthUsed = 0;
478   This->acmStreamHdr.cbDstLengthUsed = 0;
479   This->acmStreamHdr.cbSrcLength     = size;
480 
481   /* read source data */
482   hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
483                        This->acmStreamHdr.cbSrcLength,
484                        (LONG *)&This->acmStreamHdr.cbSrcLength, NULL);
485   if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
486     return hr;
487 
488   /* need to prepare stream? */
489   This->acmStreamHdr.pbDst       = buffer;
490   This->acmStreamHdr.cbDstLength = buffersize;
491   if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
492     if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
493       This->acmStreamHdr.pbDst       = NULL;
494       This->acmStreamHdr.cbDstLength = 0;
495       return AVIERR_COMPRESSOR;
496     }
497   }
498 
499   /* now do the conversion */
500   /* FIXME: use ACM_CONVERTF_* flags */
501   if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
502     hr = AVIERR_COMPRESSOR;
503 
504   This->acmStreamHdr.pbDst       = NULL;
505   This->acmStreamHdr.cbDstLength = 0;
506 
507   /* fill out return parameters if given */
508   if (bytesread != NULL)
509     *bytesread = This->acmStreamHdr.cbDstLengthUsed;
510   if (samplesread != NULL)
511     *samplesread =
512       This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
513 
514   return hr;
515 }
516 
517 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
518                                          LONG samples, LPVOID buffer,
519                                          LONG buffersize, DWORD flags,
520                                          LPLONG sampwritten,
521                                          LPLONG byteswritten)
522 {
523   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
524 
525   HRESULT hr;
526   ULONG   size;
527 
528   TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples,
529         buffer, buffersize, flags, sampwritten, byteswritten);
530 
531   /* clear return parameters if given */
532   if (sampwritten != NULL)
533     *sampwritten = 0;
534   if (byteswritten != NULL)
535     *byteswritten = 0;
536 
537   /* check parameters */
538   if (buffer == NULL && (buffersize > 0 || samples > 0))
539     return AVIERR_BADPARAM;
540 
541   /* Have we write capability? */
542   if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
543     return AVIERR_READONLY;
544 
545   /* also need a compressor */
546   if (This->has == NULL)
547     return AVIERR_NOCOMPRESSOR;
548 
549   /* map our sizes to pStream sizes */
550   size = buffersize;
551   CONVERT_THIS_to_STREAM(&size);
552   CONVERT_THIS_to_STREAM(&start);
553 
554   /* no bytes to write? -- short circuit */
555   if (size == 0) {
556     return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
557                             flags, sampwritten, byteswritten);
558   }
559 
560   /* Need to free source buffer used for reading? */
561   if (This->acmStreamHdr.pbSrc != NULL) {
562     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
563     This->acmStreamHdr.pbSrc     = NULL;
564     This->acmStreamHdr.dwSrcUser = 0;
565   }
566 
567   /* Need bigger destination buffer? */
568   if (This->acmStreamHdr.pbDst == NULL ||
569       This->acmStreamHdr.dwDstUser < size) {
570     if (This->acmStreamHdr.pbDst == NULL)
571       This->acmStreamHdr.pbDst = HeapAlloc(GetProcessHeap(), 0, size);
572     else
573       This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbDst, size);
574     if (This->acmStreamHdr.pbDst == NULL)
575       return AVIERR_MEMORY;
576     This->acmStreamHdr.dwDstUser = size;
577   }
578   This->acmStreamHdr.cbStruct        = sizeof(This->acmStreamHdr);
579   This->acmStreamHdr.cbSrcLengthUsed = 0;
580   This->acmStreamHdr.cbDstLengthUsed = 0;
581   This->acmStreamHdr.cbDstLength     = This->acmStreamHdr.dwDstUser;
582 
583   /* need to prepare stream? */
584   This->acmStreamHdr.pbSrc       = buffer;
585   This->acmStreamHdr.cbSrcLength = buffersize;
586   if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
587     if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
588       This->acmStreamHdr.pbSrc       = NULL;
589       This->acmStreamHdr.cbSrcLength = 0;
590       return AVIERR_COMPRESSOR;
591     }
592   }
593 
594   /* now do the conversion */
595   /* FIXME: use ACM_CONVERTF_* flags */
596   if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
597     hr = AVIERR_COMPRESSOR;
598   else
599     hr = AVIERR_OK;
600 
601   This->acmStreamHdr.pbSrc       = NULL;
602   This->acmStreamHdr.cbSrcLength = 0;
603 
604   if (FAILED(hr))
605     return hr;
606 
607   return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
608                           This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
609                           This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
610                           byteswritten);
611 }
612 
613 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
614                                           LONG samples)
615 {
616   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
617 
618   TRACE("(%p,%d,%d)\n", iface, start, samples);
619 
620   /* check parameters */
621   if (start < 0 || samples < 0)
622     return AVIERR_BADPARAM;
623 
624   /* Delete before start of stream? */
625   if ((DWORD)(start + samples) < This->sInfo.dwStart)
626     return AVIERR_OK;
627 
628   /* Delete after end of stream? */
629   if ((DWORD)start > This->sInfo.dwLength)
630     return AVIERR_OK;
631 
632   /* For the rest we need write capability */
633   if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
634     return AVIERR_READONLY;
635 
636   /* A compressor is also necessary */
637   if (This->has == NULL)
638     return AVIERR_NOCOMPRESSOR;
639 
640   /* map our positions to pStream positions */
641   CONVERT_THIS_to_STREAM(&start);
642   CONVERT_THIS_to_STREAM(&samples);
643 
644   return IAVIStream_Delete(This->pStream, start, samples);
645 }
646 
647 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
648                                             LPVOID lp, LPLONG lpread)
649 {
650   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
651 
652   TRACE("(%p,0x%08X,%p,%p)\n", iface, fcc, lp, lpread);
653 
654   assert(This->pStream != NULL);
655 
656   return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
657 }
658 
659 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
660                                              LPVOID lp, LONG size)
661 {
662   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
663 
664   TRACE("(%p,0x%08x,%p,%d)\n", iface, fcc, lp, size);
665 
666   assert(This->pStream != NULL);
667 
668   return IAVIStream_WriteData(This->pStream, fcc, lp, size);
669 }
670 
671 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
672                                            LPAVISTREAMINFOW info, LONG infolen)
673 {
674   FIXME("(%p,%p,%d): stub\n", iface, info, infolen);
675 
676   return E_FAIL;
677 }
678 
679 /***********************************************************************/
680 
681 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
682 {
683   HRESULT hr;
684 
685   /* pre-conditions */
686   assert(This != NULL);
687   assert(This->pStream != NULL);
688 
689   if (This->has != NULL)
690     return AVIERR_OK;
691 
692   if (This->lpInFormat == NULL) {
693     /* decode or encode the data from pStream */
694     hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
695     if (FAILED(hr))
696       return hr;
697     This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat);
698     if (This->lpInFormat == NULL)
699       return AVIERR_MEMORY;
700 
701     hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
702                                This->lpInFormat, &This->cbInFormat);
703     if (FAILED(hr))
704       return hr;
705 
706     if (This->lpOutFormat == NULL) {
707       /* we must decode to default format */
708       This->cbOutFormat = sizeof(PCMWAVEFORMAT);
709       This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
710       if (This->lpOutFormat == NULL)
711         return AVIERR_MEMORY;
712 
713       This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
714       if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
715                            This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
716         return AVIERR_NOCOMPRESSOR;
717     }
718   } else if (This->lpOutFormat == NULL)
719     return AVIERR_ERROR; /* To what should I encode? */
720 
721   if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
722                     NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
723     return AVIERR_NOCOMPRESSOR;
724 
725   /* update AVISTREAMINFO structure */
726   This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
727   This->sInfo.dwScale      = This->lpOutFormat->nBlockAlign;
728   This->sInfo.dwRate       = This->lpOutFormat->nAvgBytesPerSec;
729   This->sInfo.dwQuality    = (DWORD)ICQUALITY_DEFAULT;
730   SetRectEmpty(&This->sInfo.rcFrame);
731 
732   /* convert positions and sizes to output format */
733   CONVERT_STREAM_to_THIS(&This->sInfo.dwStart);
734   CONVERT_STREAM_to_THIS(&This->sInfo.dwLength);
735   CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize);
736 
737   return AVIERR_OK;
738 }
739 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.