ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

acmstream.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2002 Michael Günnewig
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include <assert.h>
00020 #include <stdarg.h>
00021 
00022 #include "windef.h"
00023 #include "winbase.h"
00024 #include "wingdi.h"
00025 #include "winuser.h"
00026 #include "winerror.h"
00027 #include "mmsystem.h"
00028 #include "vfw.h"
00029 #include "msacm.h"
00030 
00031 #include "avifile_private.h"
00032 
00033 #include "wine/debug.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
00036 
00037 /***********************************************************************/
00038 
00039 typedef struct _IAVIStreamImpl {
00040   /* IUnknown stuff */
00041   IAVIStream      IAVIStream_iface;
00042   LONG        ref;
00043 
00044   /* IAVIStream stuff */
00045   PAVISTREAM      pStream;
00046   AVISTREAMINFOW  sInfo;
00047 
00048   HACMSTREAM      has;
00049 
00050   LPWAVEFORMATEX  lpInFormat;
00051   LONG            cbInFormat;
00052 
00053   LPWAVEFORMATEX  lpOutFormat;
00054   LONG            cbOutFormat;
00055 
00056   ACMSTREAMHEADER acmStreamHdr;
00057 } IAVIStreamImpl;
00058 
00059 /***********************************************************************/
00060 
00061 #define CONVERT_STREAM_to_THIS(a) do { \
00062            DWORD __bytes; \
00063            acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
00064                          &__bytes, ACM_STREAMSIZEF_SOURCE); \
00065            *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
00066 
00067 #define CONVERT_THIS_to_STREAM(a) do { \
00068            DWORD __bytes; \
00069            acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
00070                          &__bytes, ACM_STREAMSIZEF_DESTINATION); \
00071            *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
00072 
00073 static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
00074 {
00075   HRESULT hr;
00076 
00077   /* pre-conditions */
00078   assert(This != NULL);
00079   assert(This->pStream != NULL);
00080 
00081   if (This->has != NULL)
00082     return AVIERR_OK;
00083 
00084   if (This->lpInFormat == NULL) {
00085     /* decode or encode the data from pStream */
00086     hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
00087     if (FAILED(hr))
00088       return hr;
00089     This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat);
00090     if (This->lpInFormat == NULL)
00091       return AVIERR_MEMORY;
00092 
00093     hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
00094                                This->lpInFormat, &This->cbInFormat);
00095     if (FAILED(hr))
00096       return hr;
00097 
00098     if (This->lpOutFormat == NULL) {
00099       /* we must decode to default format */
00100       This->cbOutFormat = sizeof(PCMWAVEFORMAT);
00101       This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
00102       if (This->lpOutFormat == NULL)
00103         return AVIERR_MEMORY;
00104 
00105       This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
00106       if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
00107                            This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
00108         return AVIERR_NOCOMPRESSOR;
00109     }
00110   } else if (This->lpOutFormat == NULL)
00111     return AVIERR_ERROR; /* To what should I encode? */
00112 
00113   if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
00114                     NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
00115     return AVIERR_NOCOMPRESSOR;
00116 
00117   /* update AVISTREAMINFO structure */
00118   This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
00119   This->sInfo.dwScale      = This->lpOutFormat->nBlockAlign;
00120   This->sInfo.dwRate       = This->lpOutFormat->nAvgBytesPerSec;
00121   This->sInfo.dwQuality    = (DWORD)ICQUALITY_DEFAULT;
00122   SetRectEmpty(&This->sInfo.rcFrame);
00123 
00124   /* convert positions and sizes to output format */
00125   CONVERT_STREAM_to_THIS(&This->sInfo.dwStart);
00126   CONVERT_STREAM_to_THIS(&This->sInfo.dwLength);
00127   CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize);
00128 
00129   return AVIERR_OK;
00130 }
00131 
00132 static inline IAVIStreamImpl *impl_from_IAVIStream(IAVIStream *iface)
00133 {
00134   return CONTAINING_RECORD(iface, IAVIStreamImpl, IAVIStream_iface);
00135 }
00136 
00137 static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
00138                           REFIID refiid, LPVOID *obj)
00139 {
00140   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00141 
00142   TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
00143 
00144   if (IsEqualGUID(&IID_IUnknown, refiid) ||
00145       IsEqualGUID(&IID_IAVIStream, refiid)) {
00146     *obj = This;
00147     IAVIStream_AddRef(iface);
00148 
00149     return S_OK;
00150   }
00151 
00152   return OLE_E_ENUM_NOMORE;
00153 }
00154 
00155 static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface)
00156 {
00157   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00158   ULONG ref = InterlockedIncrement(&This->ref);
00159 
00160   TRACE("(%p) -> %d\n", iface, ref);
00161 
00162   /* also add reference to the nested stream */
00163   if (This->pStream != NULL)
00164     IAVIStream_AddRef(This->pStream);
00165 
00166   return ref;
00167 }
00168 
00169 static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
00170 {
00171   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00172   ULONG ref = InterlockedDecrement(&This->ref);
00173 
00174   TRACE("(%p) -> %d\n", iface, ref);
00175 
00176   if (ref == 0) {
00177     /* destruct */
00178     if (This->has != NULL) {
00179       if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
00180     acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
00181       acmStreamClose(This->has, 0);
00182       This->has = NULL;
00183     }
00184     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
00185     This->acmStreamHdr.pbSrc = NULL;
00186     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
00187     This->acmStreamHdr.pbDst = NULL;
00188     if (This->lpInFormat != NULL) {
00189       HeapFree(GetProcessHeap(), 0, This->lpInFormat);
00190       This->lpInFormat = NULL;
00191       This->cbInFormat = 0;
00192     }
00193     if (This->lpOutFormat != NULL) {
00194       HeapFree(GetProcessHeap(), 0, This->lpOutFormat);
00195       This->lpOutFormat = NULL;
00196       This->cbOutFormat = 0;
00197     }
00198     if (This->pStream != NULL) {
00199       IAVIStream_Release(This->pStream);
00200       This->pStream = NULL;
00201     }
00202     HeapFree(GetProcessHeap(), 0, This);
00203 
00204     return 0;
00205   }
00206 
00207   /* also release reference to the nested stream */
00208   if (This->pStream != NULL)
00209     IAVIStream_Release(This->pStream);
00210 
00211   return ref;
00212 }
00213 
00214 /* lParam1: PAVISTREAM
00215  * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
00216  */
00217 static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
00218                       LPARAM lParam2)
00219 {
00220   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00221 
00222   TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
00223 
00224   /* check for swapped parameters */
00225   if ((LPVOID)lParam1 != NULL &&
00226       ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
00227     register LPARAM tmp = lParam1;
00228 
00229     lParam1 = lParam2;
00230     lParam2 = tmp;
00231   }
00232 
00233   if ((LPVOID)lParam1 == NULL)
00234     return AVIERR_BADPARAM;
00235 
00236   IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
00237   if (This->sInfo.fccType != streamtypeAUDIO)
00238     return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
00239 
00240   This->sInfo.fccHandler = 0; /* be paranoid */
00241 
00242   /* FIXME: check ACM version? Which version does we need? */
00243 
00244   if ((LPVOID)lParam2 != NULL) {
00245     /* We only need the format from the compress-options */
00246     if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
00247       lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
00248 
00249     if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
00250       This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
00251     else
00252       This->cbOutFormat = sizeof(PCMWAVEFORMAT);
00253 
00254     This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat);
00255     if (This->lpOutFormat == NULL)
00256       return AVIERR_MEMORY;
00257 
00258     memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
00259   } else {
00260     This->lpOutFormat = NULL;
00261     This->cbOutFormat = 0;
00262   }
00263 
00264   This->pStream = (PAVISTREAM)lParam1;
00265   IAVIStream_AddRef(This->pStream);
00266 
00267   return AVIERR_OK;
00268 }
00269 
00270 static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
00271                     LONG size)
00272 {
00273   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00274 
00275   TRACE("(%p,%p,%d)\n", iface, psi, size);
00276 
00277   if (psi == NULL)
00278     return AVIERR_BADPARAM;
00279   if (size < 0)
00280     return AVIERR_BADSIZE;
00281 
00282   /* Need codec to correct some values in structure */
00283   if (This->has == NULL) {
00284     HRESULT hr = AVIFILE_OpenCompressor(This);
00285 
00286     if (FAILED(hr))
00287       return hr;
00288   }
00289 
00290   memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
00291 
00292   if (size < (LONG)sizeof(This->sInfo))
00293     return AVIERR_BUFFERTOOSMALL;
00294   return AVIERR_OK;
00295 }
00296 
00297 static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
00298                        LONG flags)
00299 {
00300   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00301 
00302   TRACE("(%p,%d,0x%08X)\n",iface,pos,flags);
00303 
00304   if (flags & FIND_FROM_START) {
00305     pos = This->sInfo.dwStart;
00306     flags &= ~(FIND_FROM_START|FIND_PREV);
00307     flags |= FIND_NEXT;
00308   }
00309 
00310   /* convert pos from our 'space' to This->pStream's one */
00311   CONVERT_THIS_to_STREAM(&pos);
00312 
00313   /* ask stream */
00314   pos = IAVIStream_FindSample(This->pStream, pos, flags);
00315 
00316   if (pos != -1) {
00317     /* convert pos back to our 'space' if it's no size or physical pos */
00318     if ((flags & FIND_RET) == 0)
00319       CONVERT_STREAM_to_THIS(&pos);
00320   }
00321 
00322   return pos;
00323 }
00324 
00325 static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
00326                           LPVOID format, LONG *formatsize)
00327 {
00328   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00329 
00330   TRACE("(%p,%d,%p,%p)\n", iface, pos, format, formatsize);
00331 
00332   if (formatsize == NULL)
00333     return AVIERR_BADPARAM;
00334 
00335   if (This->has == NULL) {
00336     HRESULT hr = AVIFILE_OpenCompressor(This);
00337 
00338     if (FAILED(hr))
00339       return hr;
00340   }
00341 
00342   /* only interested in needed buffersize? */
00343   if (format == NULL || *formatsize <= 0) {
00344     *formatsize = This->cbOutFormat;
00345 
00346     return AVIERR_OK;
00347   }
00348 
00349   /* copy initial format (only as much as will fit) */
00350   memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
00351   if (*formatsize < This->cbOutFormat) {
00352     *formatsize = This->cbOutFormat;
00353     return AVIERR_BUFFERTOOSMALL;
00354   }
00355 
00356   *formatsize = This->cbOutFormat;
00357   return AVIERR_OK;
00358 }
00359 
00360 static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
00361                          LPVOID format, LONG formatsize)
00362 {
00363   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00364 
00365   HRESULT hr;
00366 
00367   TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);
00368 
00369   /* check parameters */
00370   if (format == NULL || formatsize <= 0)
00371     return AVIERR_BADPARAM;
00372 
00373   /* Input format already known?
00374    * Changing is unsupported, but be quiet if it's the same */
00375   if (This->lpInFormat != NULL) {
00376     if (This->cbInFormat != formatsize ||
00377     memcmp(format, This->lpInFormat, formatsize) != 0)
00378       return AVIERR_UNSUPPORTED;
00379 
00380     return AVIERR_OK;
00381   }
00382 
00383   /* Does the nested stream support writing? */
00384   if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
00385     return AVIERR_READONLY;
00386 
00387   This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, formatsize);
00388   if (This->lpInFormat == NULL)
00389     return AVIERR_MEMORY;
00390   This->cbInFormat = formatsize;
00391   memcpy(This->lpInFormat, format, formatsize);
00392 
00393   /* initialize formats and get compressor */
00394   hr = AVIFILE_OpenCompressor(This);
00395   if (FAILED(hr))
00396     return hr;
00397 
00398   CONVERT_THIS_to_STREAM(&pos);
00399 
00400   /* tell the nested stream the new format */
00401   return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
00402                   This->cbOutFormat);
00403 }
00404 
00405 static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
00406                     LONG samples, LPVOID buffer,
00407                     LONG buffersize, LPLONG bytesread,
00408                     LPLONG samplesread)
00409 {
00410   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00411 
00412   HRESULT hr;
00413   DWORD   size;
00414 
00415   TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer,
00416     buffersize, bytesread, samplesread);
00417 
00418   /* clear return parameters if given */
00419   if (bytesread != NULL)
00420     *bytesread = 0;
00421   if (samplesread != NULL)
00422     *samplesread = 0;
00423 
00424   /* Do we have our compressor? */
00425   if (This->has == NULL) {
00426     hr = AVIFILE_OpenCompressor(This);
00427 
00428     if (FAILED(hr))
00429       return hr;
00430   }
00431 
00432   /* only need to pass through? */
00433   if (This->cbInFormat == This->cbOutFormat &&
00434       memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
00435     return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
00436                bytesread, samplesread);
00437   }
00438 
00439   /* read as much as fit? */
00440   if (samples == -1)
00441     samples = buffersize / This->lpOutFormat->nBlockAlign;
00442   /* limit to buffersize */
00443   if (samples * This->lpOutFormat->nBlockAlign > buffersize)
00444     samples = buffersize / This->lpOutFormat->nBlockAlign;
00445 
00446   /* only return needed size? */
00447   if (buffer == NULL || buffersize <= 0 || samples == 0) {
00448     if (bytesread == NULL && samplesread == NULL)
00449       return AVIERR_BADPARAM;
00450 
00451     if (bytesread != NULL)
00452       *bytesread = samples * This->lpOutFormat->nBlockAlign;
00453     if (samplesread != NULL)
00454       *samplesread = samples;
00455 
00456     return AVIERR_OK;
00457   }
00458 
00459   /* map our positions to pStream positions */
00460   CONVERT_THIS_to_STREAM(&start);
00461 
00462   /* our needed internal buffersize */
00463   size = samples * This->lpInFormat->nBlockAlign;
00464 
00465   /* Need to free destination buffer used for writing? */
00466   if (This->acmStreamHdr.pbDst != NULL) {
00467     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst);
00468     This->acmStreamHdr.pbDst     = NULL;
00469     This->acmStreamHdr.dwDstUser = 0;
00470   }
00471 
00472   /* need bigger source buffer? */
00473   if (This->acmStreamHdr.pbSrc == NULL ||
00474       This->acmStreamHdr.dwSrcUser < size) {
00475     if (This->acmStreamHdr.pbSrc == NULL)
00476       This->acmStreamHdr.pbSrc = HeapAlloc(GetProcessHeap(), 0, size);
00477     else
00478       This->acmStreamHdr.pbSrc = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc, size);
00479     if (This->acmStreamHdr.pbSrc == NULL)
00480       return AVIERR_MEMORY;
00481     This->acmStreamHdr.dwSrcUser = size;
00482   }
00483 
00484   This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
00485   This->acmStreamHdr.cbSrcLengthUsed = 0;
00486   This->acmStreamHdr.cbDstLengthUsed = 0;
00487   This->acmStreamHdr.cbSrcLength     = size;
00488 
00489   /* read source data */
00490   hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
00491                This->acmStreamHdr.cbSrcLength,
00492                (LONG *)&This->acmStreamHdr.cbSrcLength, NULL);
00493   if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
00494     return hr;
00495 
00496   /* need to prepare stream? */
00497   This->acmStreamHdr.pbDst       = buffer;
00498   This->acmStreamHdr.cbDstLength = buffersize;
00499   if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
00500     if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
00501       This->acmStreamHdr.pbDst       = NULL;
00502       This->acmStreamHdr.cbDstLength = 0;
00503       return AVIERR_COMPRESSOR;
00504     }
00505   }
00506 
00507   /* now do the conversion */
00508   /* FIXME: use ACM_CONVERTF_* flags */
00509   if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
00510     hr = AVIERR_COMPRESSOR;
00511 
00512   This->acmStreamHdr.pbDst       = NULL;
00513   This->acmStreamHdr.cbDstLength = 0;
00514 
00515   /* fill out return parameters if given */
00516   if (bytesread != NULL)
00517     *bytesread = This->acmStreamHdr.cbDstLengthUsed;
00518   if (samplesread != NULL)
00519     *samplesread =
00520       This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
00521 
00522   return hr;
00523 }
00524 
00525 static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
00526                      LONG samples, LPVOID buffer,
00527                      LONG buffersize, DWORD flags,
00528                      LPLONG sampwritten,
00529                      LPLONG byteswritten)
00530 {
00531   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00532 
00533   HRESULT hr;
00534   ULONG   size;
00535 
00536   TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples,
00537     buffer, buffersize, flags, sampwritten, byteswritten);
00538 
00539   /* clear return parameters if given */
00540   if (sampwritten != NULL)
00541     *sampwritten = 0;
00542   if (byteswritten != NULL)
00543     *byteswritten = 0;
00544 
00545   /* check parameters */
00546   if (buffer == NULL && (buffersize > 0 || samples > 0))
00547     return AVIERR_BADPARAM;
00548 
00549   /* Have we write capability? */
00550   if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
00551     return AVIERR_READONLY;
00552 
00553   /* also need a compressor */
00554   if (This->has == NULL)
00555     return AVIERR_NOCOMPRESSOR;
00556 
00557   /* map our sizes to pStream sizes */
00558   size = buffersize;
00559   CONVERT_THIS_to_STREAM(&size);
00560   CONVERT_THIS_to_STREAM(&start);
00561 
00562   /* no bytes to write? -- short circuit */
00563   if (size == 0) {
00564     return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
00565                 flags, sampwritten, byteswritten);
00566   }
00567 
00568   /* Need to free source buffer used for reading? */
00569   if (This->acmStreamHdr.pbSrc != NULL) {
00570     HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc);
00571     This->acmStreamHdr.pbSrc     = NULL;
00572     This->acmStreamHdr.dwSrcUser = 0;
00573   }
00574 
00575   /* Need bigger destination buffer? */
00576   if (This->acmStreamHdr.pbDst == NULL ||
00577       This->acmStreamHdr.dwDstUser < size) {
00578     if (This->acmStreamHdr.pbDst == NULL)
00579       This->acmStreamHdr.pbDst = HeapAlloc(GetProcessHeap(), 0, size);
00580     else
00581       This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbDst, size);
00582     if (This->acmStreamHdr.pbDst == NULL)
00583       return AVIERR_MEMORY;
00584     This->acmStreamHdr.dwDstUser = size;
00585   }
00586   This->acmStreamHdr.cbStruct        = sizeof(This->acmStreamHdr);
00587   This->acmStreamHdr.cbSrcLengthUsed = 0;
00588   This->acmStreamHdr.cbDstLengthUsed = 0;
00589   This->acmStreamHdr.cbDstLength     = This->acmStreamHdr.dwDstUser;
00590 
00591   /* need to prepare stream? */
00592   This->acmStreamHdr.pbSrc       = buffer;
00593   This->acmStreamHdr.cbSrcLength = buffersize;
00594   if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
00595     if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
00596       This->acmStreamHdr.pbSrc       = NULL;
00597       This->acmStreamHdr.cbSrcLength = 0;
00598       return AVIERR_COMPRESSOR;
00599     }
00600   }
00601 
00602   /* now do the conversion */
00603   /* FIXME: use ACM_CONVERTF_* flags */
00604   if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
00605     hr = AVIERR_COMPRESSOR;
00606   else
00607     hr = AVIERR_OK;
00608 
00609   This->acmStreamHdr.pbSrc       = NULL;
00610   This->acmStreamHdr.cbSrcLength = 0;
00611 
00612   if (FAILED(hr))
00613     return hr;
00614 
00615   return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
00616               This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
00617               This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
00618               byteswritten);
00619 }
00620 
00621 static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
00622                       LONG samples)
00623 {
00624   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00625 
00626   TRACE("(%p,%d,%d)\n", iface, start, samples);
00627 
00628   /* check parameters */
00629   if (start < 0 || samples < 0)
00630     return AVIERR_BADPARAM;
00631 
00632   /* Delete before start of stream? */
00633   if ((DWORD)(start + samples) < This->sInfo.dwStart)
00634     return AVIERR_OK;
00635 
00636   /* Delete after end of stream? */
00637   if ((DWORD)start > This->sInfo.dwLength)
00638     return AVIERR_OK;
00639 
00640   /* For the rest we need write capability */
00641   if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
00642     return AVIERR_READONLY;
00643 
00644   /* A compressor is also necessary */
00645   if (This->has == NULL)
00646     return AVIERR_NOCOMPRESSOR;
00647 
00648   /* map our positions to pStream positions */
00649   CONVERT_THIS_to_STREAM(&start);
00650   CONVERT_THIS_to_STREAM(&samples);
00651 
00652   return IAVIStream_Delete(This->pStream, start, samples);
00653 }
00654 
00655 static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
00656                         LPVOID lp, LPLONG lpread)
00657 {
00658   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00659 
00660   TRACE("(%p,0x%08X,%p,%p)\n", iface, fcc, lp, lpread);
00661 
00662   assert(This->pStream != NULL);
00663 
00664   return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
00665 }
00666 
00667 static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
00668                          LPVOID lp, LONG size)
00669 {
00670   IAVIStreamImpl *This = impl_from_IAVIStream(iface);
00671 
00672   TRACE("(%p,0x%08x,%p,%d)\n", iface, fcc, lp, size);
00673 
00674   assert(This->pStream != NULL);
00675 
00676   return IAVIStream_WriteData(This->pStream, fcc, lp, size);
00677 }
00678 
00679 static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
00680                        LPAVISTREAMINFOW info, LONG infolen)
00681 {
00682   FIXME("(%p,%p,%d): stub\n", iface, info, infolen);
00683 
00684   return E_FAIL;
00685 }
00686 
00687 static const struct IAVIStreamVtbl iacmst = {
00688   ACMStream_fnQueryInterface,
00689   ACMStream_fnAddRef,
00690   ACMStream_fnRelease,
00691   ACMStream_fnCreate,
00692   ACMStream_fnInfo,
00693   ACMStream_fnFindSample,
00694   ACMStream_fnReadFormat,
00695   ACMStream_fnSetFormat,
00696   ACMStream_fnRead,
00697   ACMStream_fnWrite,
00698   ACMStream_fnDelete,
00699   ACMStream_fnReadData,
00700   ACMStream_fnWriteData,
00701   ACMStream_fnSetInfo
00702 };
00703 
00704 HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppv)
00705 {
00706   IAVIStreamImpl *pstream;
00707   HRESULT         hr;
00708 
00709   assert(riid != NULL && ppv != NULL);
00710 
00711   *ppv = NULL;
00712 
00713   pstream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAVIStreamImpl));
00714   if (pstream == NULL)
00715     return AVIERR_MEMORY;
00716 
00717   pstream->IAVIStream_iface.lpVtbl = &iacmst;
00718 
00719   hr = IAVIStream_QueryInterface(&pstream->IAVIStream_iface, riid, ppv);
00720   if (FAILED(hr))
00721     HeapFree(GetProcessHeap(), 0, pstream);
00722 
00723   return hr;
00724 }

Generated on Sat May 26 2012 04:21:22 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.