Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenacmstream.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
1.7.6.1
|