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

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

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

~ [ 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.