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

getframe.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 doxygen 1.7.6.1

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