Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengetframe.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2002-2003 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 <stdarg.h> 00020 00021 #include "windef.h" 00022 #include "winbase.h" 00023 #include "wingdi.h" 00024 #include "winuser.h" 00025 #include "vfw.h" 00026 00027 #include "avifile_private.h" 00028 00029 #include "wine/debug.h" 00030 00031 WINE_DEFAULT_DEBUG_CHANNEL(avifile); 00032 00033 #ifndef DIBPTR 00034 #define DIBPTR(lp) ((LPBYTE)(lp) + (lp)->biSize + \ 00035 (lp)->biClrUsed * sizeof(RGBQUAD)) 00036 #endif 00037 00038 /***********************************************************************/ 00039 00040 typedef struct _IGetFrameImpl { 00041 /* IUnknown stuff */ 00042 IGetFrame IGetFrame_iface; 00043 LONG ref; 00044 00045 /* IGetFrame stuff */ 00046 BOOL bFixedStream; 00047 PAVISTREAM pStream; 00048 00049 LPVOID lpInBuffer; 00050 LONG cbInBuffer; 00051 LPBITMAPINFOHEADER lpInFormat; 00052 LONG cbInFormat; 00053 00054 LONG lCurrentFrame; 00055 LPBITMAPINFOHEADER lpOutFormat; 00056 LPVOID lpOutBuffer; 00057 00058 HIC hic; 00059 BOOL bResize; 00060 DWORD x; 00061 DWORD y; 00062 DWORD dx; 00063 DWORD dy; 00064 00065 BOOL bFormatChanges; 00066 DWORD dwFormatChangeCount; 00067 DWORD dwEditCount; 00068 } IGetFrameImpl; 00069 00070 /***********************************************************************/ 00071 00072 static inline IGetFrameImpl *impl_from_IGetFrame(IGetFrame *iface) 00073 { 00074 return CONTAINING_RECORD(iface, IGetFrameImpl, IGetFrame_iface); 00075 } 00076 00077 static void AVIFILE_CloseCompressor(IGetFrameImpl *This) 00078 { 00079 if (This->lpInFormat != This->lpOutFormat) { 00080 HeapFree(GetProcessHeap(), 0, This->lpOutFormat); 00081 This->lpOutFormat = NULL; 00082 } 00083 HeapFree(GetProcessHeap(), 0, This->lpInFormat); 00084 This->lpInFormat = NULL; 00085 if (This->hic != NULL) { 00086 if (This->bResize) 00087 ICDecompressExEnd(This->hic); 00088 else 00089 ICDecompressEnd(This->hic); 00090 ICClose(This->hic); 00091 This->hic = NULL; 00092 } 00093 } 00094 00095 static HRESULT WINAPI IGetFrame_fnQueryInterface(IGetFrame *iface, 00096 REFIID refiid, LPVOID *obj) 00097 { 00098 IGetFrameImpl *This = impl_from_IGetFrame(iface); 00099 00100 TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj); 00101 00102 if (IsEqualGUID(&IID_IUnknown, refiid) || 00103 IsEqualGUID(&IID_IGetFrame, refiid)) { 00104 *obj = iface; 00105 IGetFrame_AddRef(iface); 00106 return S_OK; 00107 } 00108 00109 return OLE_E_ENUM_NOMORE; 00110 } 00111 00112 static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame *iface) 00113 { 00114 IGetFrameImpl *This = impl_from_IGetFrame(iface); 00115 ULONG ref = InterlockedIncrement(&This->ref); 00116 00117 TRACE("(%p)\n", iface); 00118 00119 return ref; 00120 } 00121 00122 static ULONG WINAPI IGetFrame_fnRelease(IGetFrame *iface) 00123 { 00124 IGetFrameImpl *This = impl_from_IGetFrame(iface); 00125 ULONG ref = InterlockedDecrement(&This->ref); 00126 00127 TRACE("(%p)\n", iface); 00128 00129 if (!ref) { 00130 AVIFILE_CloseCompressor(This); 00131 if (This->pStream != NULL) { 00132 IAVIStream_Release(This->pStream); 00133 This->pStream = NULL; 00134 } 00135 00136 HeapFree(GetProcessHeap(), 0, iface); 00137 return 0; 00138 } 00139 00140 return ref; 00141 } 00142 00143 static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame *iface, LONG lPos) 00144 { 00145 IGetFrameImpl *This = impl_from_IGetFrame(iface); 00146 00147 LONG readBytes; 00148 LONG readSamples; 00149 00150 TRACE("(%p,%d)\n", iface, lPos); 00151 00152 /* We don't want negative start values! -- marks invalid buffer content */ 00153 if (lPos < 0) 00154 return NULL; 00155 00156 /* check state */ 00157 if (This->pStream == NULL) 00158 return NULL; 00159 if (This->lpInFormat == NULL) 00160 return NULL; 00161 00162 /* Could stream have changed? */ 00163 if (! This->bFixedStream) { 00164 AVISTREAMINFOW sInfo; 00165 00166 IAVIStream_Info(This->pStream, &sInfo, sizeof(sInfo)); 00167 00168 if (sInfo.dwEditCount != This->dwEditCount) { 00169 This->dwEditCount = sInfo.dwEditCount; 00170 This->lCurrentFrame = -1; 00171 } 00172 00173 if (sInfo.dwFormatChangeCount != This->dwFormatChangeCount) { 00174 /* stream has changed */ 00175 if (This->lpOutFormat != NULL) { 00176 BITMAPINFOHEADER bi; 00177 00178 bi = *This->lpOutFormat; 00179 AVIFILE_CloseCompressor(This); 00180 00181 if (FAILED(IGetFrame_SetFormat(iface, &bi, NULL, 0, 0, -1, -1))) { 00182 if (FAILED(IGetFrame_SetFormat(iface, NULL, NULL, 0, 0, -1, -1))) 00183 return NULL; 00184 } 00185 } else if (FAILED(IGetFrame_SetFormat(iface, NULL, NULL, 0, 0, -1, -1))) 00186 return NULL; 00187 } 00188 } 00189 00190 if (lPos != This->lCurrentFrame) { 00191 LONG lNext = IAVIStream_FindSample(This->pStream,lPos,FIND_KEY|FIND_PREV); 00192 00193 if (lNext == -1) 00194 return NULL; /* frame doesn't exist */ 00195 if (lNext <= This->lCurrentFrame && This->lCurrentFrame < lPos) 00196 lNext = This->lCurrentFrame + 1; 00197 00198 for (; lNext <= lPos; lNext++) { 00199 /* new format for this frame? */ 00200 if (This->bFormatChanges) { 00201 IAVIStream_ReadFormat(This->pStream, lNext, 00202 This->lpInFormat, &This->cbInFormat); 00203 if (This->lpOutFormat != NULL) { 00204 if (This->lpOutFormat->biBitCount <= 8) 00205 ICDecompressGetPalette(This->hic, This->lpInFormat, 00206 This->lpOutFormat); 00207 } 00208 } 00209 00210 /* read input frame */ 00211 while (FAILED(AVIStreamRead(This->pStream, lNext, 1, This->lpInBuffer, 00212 This->cbInBuffer, &readBytes, &readSamples))) { 00213 /* not enough memory for input buffer? */ 00214 readBytes = 0; 00215 if (FAILED(AVIStreamSampleSize(This->pStream, lNext, &readBytes))) 00216 return NULL; /* bad thing, but bad things will happen */ 00217 if (readBytes <= 0) { 00218 ERR(": IAVIStream::Read doesn't return needed bytes!\n"); 00219 return NULL; 00220 } 00221 00222 /* IAVIStream::Read failed because of other reasons not buffersize? */ 00223 if (This->cbInBuffer >= readBytes) 00224 break; 00225 This->cbInBuffer = This->cbInFormat + readBytes; 00226 This->lpInFormat = HeapReAlloc(GetProcessHeap(), 0, This->lpInFormat, This->cbInBuffer); 00227 if (This->lpInFormat == NULL) 00228 return NULL; /* out of memory */ 00229 This->lpInBuffer = (BYTE*)This->lpInFormat + This->cbInFormat; 00230 } 00231 00232 if (readSamples != 1) { 00233 ERR(": no frames read\n"); 00234 return NULL; 00235 } 00236 if (readBytes != 0) { 00237 This->lpInFormat->biSizeImage = readBytes; 00238 00239 /* nothing to decompress? */ 00240 if (This->hic == NULL) { 00241 This->lCurrentFrame = lPos; 00242 return This->lpInFormat; 00243 } 00244 00245 if (This->bResize) { 00246 ICDecompressEx(This->hic,0,This->lpInFormat,This->lpInBuffer,0,0, 00247 This->lpInFormat->biWidth,This->lpInFormat->biHeight, 00248 This->lpOutFormat,This->lpOutBuffer,This->x,This->y, 00249 This->dx,This->dy); 00250 } else { 00251 ICDecompress(This->hic, 0, This->lpInFormat, This->lpInBuffer, 00252 This->lpOutFormat, This->lpOutBuffer); 00253 } 00254 } 00255 } /* for (lNext < lPos) */ 00256 } /* if (This->lCurrentFrame != lPos) */ 00257 00258 return (This->hic == NULL ? This->lpInFormat : This->lpOutFormat); 00259 } 00260 00261 static HRESULT WINAPI IGetFrame_fnBegin(IGetFrame *iface, LONG lStart, 00262 LONG lEnd, LONG lRate) 00263 { 00264 IGetFrameImpl *This = impl_from_IGetFrame(iface); 00265 00266 TRACE("(%p,%d,%d,%d)\n", iface, lStart, lEnd, lRate); 00267 00268 This->bFixedStream = TRUE; 00269 00270 return (IGetFrame_GetFrame(iface, lStart) ? AVIERR_OK : AVIERR_ERROR); 00271 } 00272 00273 static HRESULT WINAPI IGetFrame_fnEnd(IGetFrame *iface) 00274 { 00275 IGetFrameImpl *This = impl_from_IGetFrame(iface); 00276 00277 TRACE("(%p)\n", iface); 00278 00279 This->bFixedStream = FALSE; 00280 00281 return AVIERR_OK; 00282 } 00283 00284 static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame *iface, 00285 LPBITMAPINFOHEADER lpbiWanted, 00286 LPVOID lpBits, INT x, INT y, 00287 INT dx, INT dy) 00288 { 00289 IGetFrameImpl *This = impl_from_IGetFrame(iface); 00290 00291 AVISTREAMINFOW sInfo; 00292 LPBITMAPINFOHEADER lpbi = lpbiWanted; 00293 BOOL bBestDisplay = FALSE; 00294 00295 TRACE("(%p,%p,%p,%d,%d,%d,%d)\n", iface, lpbiWanted, lpBits, 00296 x, y, dx, dy); 00297 00298 if (This->pStream == NULL) 00299 return AVIERR_ERROR; 00300 00301 if (lpbiWanted == (LPBITMAPINFOHEADER)AVIGETFRAMEF_BESTDISPLAYFMT) { 00302 lpbi = NULL; 00303 bBestDisplay = TRUE; 00304 } 00305 00306 IAVIStream_Info(This->pStream, &sInfo, sizeof(sInfo)); 00307 if (sInfo.fccType != streamtypeVIDEO) 00308 return AVIERR_UNSUPPORTED; 00309 00310 This->bFormatChanges = 00311 (sInfo.dwFlags & AVISTREAMINFO_FORMATCHANGES ? TRUE : FALSE ); 00312 This->dwFormatChangeCount = sInfo.dwFormatChangeCount; 00313 This->dwEditCount = sInfo.dwEditCount; 00314 This->lCurrentFrame = -1; 00315 00316 /* get input format from stream */ 00317 if (This->lpInFormat == NULL) { 00318 HRESULT hr; 00319 00320 This->cbInBuffer = (LONG)sInfo.dwSuggestedBufferSize; 00321 if (This->cbInBuffer == 0) 00322 This->cbInBuffer = 1024; 00323 00324 IAVIStream_ReadFormat(This->pStream, sInfo.dwStart, 00325 NULL, &This->cbInFormat); 00326 00327 This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat + This->cbInBuffer); 00328 if (This->lpInFormat == NULL) { 00329 AVIFILE_CloseCompressor(This); 00330 return AVIERR_MEMORY; 00331 } 00332 00333 hr = IAVIStream_ReadFormat(This->pStream, sInfo.dwStart, This->lpInFormat, &This->cbInFormat); 00334 if (FAILED(hr)) { 00335 AVIFILE_CloseCompressor(This); 00336 return hr; 00337 } 00338 00339 This->lpInBuffer = ((LPBYTE)This->lpInFormat) + This->cbInFormat; 00340 } 00341 00342 /* check input format */ 00343 if (This->lpInFormat->biClrUsed == 0 && This->lpInFormat->biBitCount <= 8) 00344 This->lpInFormat->biClrUsed = 1u << This->lpInFormat->biBitCount; 00345 if (This->lpInFormat->biSizeImage == 0 && 00346 This->lpInFormat->biCompression == BI_RGB) { 00347 This->lpInFormat->biSizeImage = 00348 DIBWIDTHBYTES(*This->lpInFormat) * This->lpInFormat->biHeight; 00349 } 00350 00351 /* only to pass through? */ 00352 if (This->lpInFormat->biCompression == BI_RGB && lpBits == NULL) { 00353 if (lpbi == NULL || 00354 (lpbi->biCompression == BI_RGB && 00355 lpbi->biWidth == This->lpInFormat->biWidth && 00356 lpbi->biHeight == This->lpInFormat->biHeight && 00357 lpbi->biBitCount == This->lpInFormat->biBitCount)) { 00358 This->lpOutFormat = This->lpInFormat; 00359 This->lpOutBuffer = DIBPTR(This->lpInFormat); 00360 return AVIERR_OK; 00361 } 00362 } 00363 00364 /* need memory for output format? */ 00365 if (This->lpOutFormat == NULL) { 00366 This->lpOutFormat = 00367 HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 00368 if (This->lpOutFormat == NULL) { 00369 AVIFILE_CloseCompressor(This); 00370 return AVIERR_MEMORY; 00371 } 00372 } 00373 00374 /* need handle to video compressor */ 00375 if (This->hic == NULL) { 00376 FOURCC fccHandler; 00377 00378 if (This->lpInFormat->biCompression == BI_RGB) 00379 fccHandler = comptypeDIB; 00380 else if (This->lpInFormat->biCompression == BI_RLE8) 00381 fccHandler = mmioFOURCC('R','L','E',' '); 00382 else 00383 fccHandler = sInfo.fccHandler; 00384 00385 if (lpbi != NULL) { 00386 if (lpbi->biWidth == 0) 00387 lpbi->biWidth = This->lpInFormat->biWidth; 00388 if (lpbi->biHeight == 0) 00389 lpbi->biHeight = This->lpInFormat->biHeight; 00390 } 00391 00392 This->hic = ICLocate(ICTYPE_VIDEO, fccHandler, This->lpInFormat, lpbi, ICMODE_DECOMPRESS); 00393 if (This->hic == NULL) { 00394 AVIFILE_CloseCompressor(This); 00395 return AVIERR_NOCOMPRESSOR; 00396 } 00397 } 00398 00399 /* output format given? */ 00400 if (lpbi != NULL) { 00401 /* check the given output format ... */ 00402 if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8) 00403 lpbi->biClrUsed = 1u << lpbi->biBitCount; 00404 00405 /* ... and remember it */ 00406 memcpy(This->lpOutFormat, lpbi, 00407 lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD)); 00408 if (lpbi->biBitCount <= 8) 00409 ICDecompressGetPalette(This->hic, This->lpInFormat, This->lpOutFormat); 00410 00411 return AVIERR_OK; 00412 } else { 00413 if (bBestDisplay) { 00414 ICGetDisplayFormat(This->hic, This->lpInFormat, 00415 This->lpOutFormat, 0, dx, dy); 00416 } else if (ICDecompressGetFormat(This->hic, This->lpInFormat, 00417 This->lpOutFormat) < 0) { 00418 AVIFILE_CloseCompressor(This); 00419 return AVIERR_NOCOMPRESSOR; 00420 } 00421 00422 /* check output format */ 00423 if (This->lpOutFormat->biClrUsed == 0 && 00424 This->lpOutFormat->biBitCount <= 8) 00425 This->lpOutFormat->biClrUsed = 1u << This->lpOutFormat->biBitCount; 00426 if (This->lpOutFormat->biSizeImage == 0 && 00427 This->lpOutFormat->biCompression == BI_RGB) { 00428 This->lpOutFormat->biSizeImage = 00429 DIBWIDTHBYTES(*This->lpOutFormat) * This->lpOutFormat->biHeight; 00430 } 00431 00432 if (lpBits == NULL) { 00433 register DWORD size = This->lpOutFormat->biClrUsed * sizeof(RGBQUAD); 00434 00435 size += This->lpOutFormat->biSize + This->lpOutFormat->biSizeImage; 00436 This->lpOutFormat = HeapReAlloc(GetProcessHeap(), 0, This->lpOutFormat, size); 00437 if (This->lpOutFormat == NULL) { 00438 AVIFILE_CloseCompressor(This); 00439 return AVIERR_MEMORY; 00440 } 00441 This->lpOutBuffer = DIBPTR(This->lpOutFormat); 00442 } else 00443 This->lpOutBuffer = lpBits; 00444 00445 /* for user size was irrelevant */ 00446 if (dx == -1) 00447 dx = This->lpOutFormat->biWidth; 00448 if (dy == -1) 00449 dy = This->lpOutFormat->biHeight; 00450 00451 /* need to resize? */ 00452 if (x != 0 || y != 0) { 00453 if (dy == This->lpOutFormat->biHeight && 00454 dx == This->lpOutFormat->biWidth) 00455 This->bResize = FALSE; 00456 else 00457 This->bResize = TRUE; 00458 } 00459 00460 if (This->bResize) { 00461 This->x = x; 00462 This->y = y; 00463 This->dx = dx; 00464 This->dy = dy; 00465 00466 if (ICDecompressExBegin(This->hic,0,This->lpInFormat,This->lpInBuffer,0, 00467 0,This->lpInFormat->biWidth, 00468 This->lpInFormat->biHeight,This->lpOutFormat, 00469 This->lpOutBuffer, x, y, dx, dy) == ICERR_OK) 00470 return AVIERR_OK; 00471 } else if (ICDecompressBegin(This->hic, This->lpInFormat, 00472 This->lpOutFormat) == ICERR_OK) 00473 return AVIERR_OK; 00474 00475 AVIFILE_CloseCompressor(This); 00476 00477 return AVIERR_COMPRESSOR; 00478 } 00479 } 00480 00481 static const struct IGetFrameVtbl igetframeVtbl = { 00482 IGetFrame_fnQueryInterface, 00483 IGetFrame_fnAddRef, 00484 IGetFrame_fnRelease, 00485 IGetFrame_fnGetFrame, 00486 IGetFrame_fnBegin, 00487 IGetFrame_fnEnd, 00488 IGetFrame_fnSetFormat 00489 }; 00490 00491 PGETFRAME AVIFILE_CreateGetFrame(PAVISTREAM pStream) 00492 { 00493 IGetFrameImpl *pg; 00494 00495 /* check parameter */ 00496 if (pStream == NULL) 00497 return NULL; 00498 00499 pg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGetFrameImpl)); 00500 if (pg != NULL) { 00501 pg->IGetFrame_iface.lpVtbl = &igetframeVtbl; 00502 pg->ref = 1; 00503 pg->lCurrentFrame = -1; 00504 pg->pStream = pStream; 00505 IAVIStream_AddRef(pStream); 00506 } 00507 00508 return (PGETFRAME)pg; 00509 } 00510 00511 /***********************************************************************/ Generated on Sat May 26 2012 04:21:23 for ReactOS by
1.7.6.1
|