📄 getframe.c
字号:
/*
* Copyright 2002-2003 Michael G黱newig
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "wingdi.h"
#include "winuser.h"
#include "vfw.h"
#include "avifile_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(avifile);
#ifndef DIBPTR
#define DIBPTR(lp) ((LPBYTE)(lp) + (lp)->biSize + \
(lp)->biClrUsed * sizeof(RGBQUAD))
#endif
/***********************************************************************/
static HRESULT WINAPI IGetFrame_fnQueryInterface(IGetFrame *iface,
REFIID refiid, LPVOID *obj);
static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame *iface);
static ULONG WINAPI IGetFrame_fnRelease(IGetFrame *iface);
static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame *iface, LONG lPos);
static HRESULT WINAPI IGetFrame_fnBegin(IGetFrame *iface, LONG lStart,
LONG lEnd, LONG lRate);
static HRESULT WINAPI IGetFrame_fnEnd(IGetFrame *iface);
static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame *iface,
LPBITMAPINFOHEADER lpbi,
LPVOID lpBits, INT x, INT y,
INT dx, INT dy);
static const struct IGetFrameVtbl igetframeVtbl = {
IGetFrame_fnQueryInterface,
IGetFrame_fnAddRef,
IGetFrame_fnRelease,
IGetFrame_fnGetFrame,
IGetFrame_fnBegin,
IGetFrame_fnEnd,
IGetFrame_fnSetFormat
};
typedef struct _IGetFrameImpl {
/* IUnknown stuff */
const IGetFrameVtbl *lpVtbl;
LONG ref;
/* IGetFrame stuff */
BOOL bFixedStream;
PAVISTREAM pStream;
LPVOID lpInBuffer;
LONG cbInBuffer;
LPBITMAPINFOHEADER lpInFormat;
LONG cbInFormat;
LONG lCurrentFrame;
LPBITMAPINFOHEADER lpOutFormat;
LPVOID lpOutBuffer;
HIC hic;
BOOL bResize;
DWORD x;
DWORD y;
DWORD dx;
DWORD dy;
BOOL bFormatChanges;
DWORD dwFormatChangeCount;
DWORD dwEditCount;
} IGetFrameImpl;
/***********************************************************************/
static void AVIFILE_CloseCompressor(IGetFrameImpl *This)
{
if (This->lpInFormat != This->lpOutFormat) {
HeapFree(GetProcessHeap(), 0, This->lpOutFormat);
This->lpOutFormat = NULL;
}
HeapFree(GetProcessHeap(), 0, This->lpInFormat);
This->lpInFormat = NULL;
if (This->hic != NULL) {
if (This->bResize)
ICDecompressExEnd(This->hic);
else
ICDecompressEnd(This->hic);
ICClose(This->hic);
This->hic = NULL;
}
}
PGETFRAME AVIFILE_CreateGetFrame(PAVISTREAM pStream)
{
IGetFrameImpl *pg;
/* check parameter */
if (pStream == NULL)
return NULL;
pg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGetFrameImpl));
if (pg != NULL) {
pg->lpVtbl = &igetframeVtbl;
pg->ref = 1;
pg->lCurrentFrame = -1;
pg->pStream = pStream;
IAVIStream_AddRef(pStream);
}
return (PGETFRAME)pg;
}
static HRESULT WINAPI IGetFrame_fnQueryInterface(IGetFrame *iface,
REFIID refiid, LPVOID *obj)
{
IGetFrameImpl *This = (IGetFrameImpl *)iface;
TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
if (IsEqualGUID(&IID_IUnknown, refiid) ||
IsEqualGUID(&IID_IGetFrame, refiid)) {
*obj = iface;
return S_OK;
}
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame *iface)
{
IGetFrameImpl *This = (IGetFrameImpl *)iface;
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)\n", iface);
return ref;
}
static ULONG WINAPI IGetFrame_fnRelease(IGetFrame *iface)
{
IGetFrameImpl *This = (IGetFrameImpl *)iface;
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)\n", iface);
if (!ref) {
AVIFILE_CloseCompressor(This);
if (This->pStream != NULL) {
IAVIStream_Release(This->pStream);
This->pStream = NULL;
}
HeapFree(GetProcessHeap(), 0, iface);
return 0;
}
return ref;
}
static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame *iface, LONG lPos)
{
IGetFrameImpl *This = (IGetFrameImpl *)iface;
LONG readBytes;
LONG readSamples;
TRACE("(%p,%d)\n", iface, lPos);
/* We don't want negative start values! -- marks invalid buffer content */
if (lPos < 0)
return NULL;
/* check state */
if (This->pStream == NULL)
return NULL;
if (This->lpInFormat == NULL)
return NULL;
/* Could stream have changed? */
if (! This->bFixedStream) {
AVISTREAMINFOW sInfo;
IAVIStream_Info(This->pStream, &sInfo, sizeof(sInfo));
if (sInfo.dwEditCount != This->dwEditCount) {
This->dwEditCount = sInfo.dwEditCount;
This->lCurrentFrame = -1;
}
if (sInfo.dwFormatChangeCount != This->dwFormatChangeCount) {
/* stream has changed */
if (This->lpOutFormat != NULL) {
BITMAPINFOHEADER bi;
memcpy(&bi, This->lpOutFormat, sizeof(bi));
AVIFILE_CloseCompressor(This);
if (FAILED(IGetFrame_SetFormat(iface, &bi, NULL, 0, 0, -1, -1))) {
if (FAILED(IGetFrame_SetFormat(iface, NULL, NULL, 0, 0, -1, -1)))
return NULL;
}
} else if (FAILED(IGetFrame_SetFormat(iface, NULL, NULL, 0, 0, -1, -1)))
return NULL;
}
}
if (lPos != This->lCurrentFrame) {
LONG lNext = IAVIStream_FindSample(This->pStream,lPos,FIND_KEY|FIND_PREV);
if (lNext == -1)
return NULL; /* frame doesn't exist */
if (lNext <= This->lCurrentFrame && This->lCurrentFrame < lPos)
lNext = This->lCurrentFrame + 1;
for (; lNext <= lPos; lNext++) {
/* new format for this frame? */
if (This->bFormatChanges) {
IAVIStream_ReadFormat(This->pStream, lNext,
This->lpInFormat, &This->cbInFormat);
if (This->lpOutFormat != NULL) {
if (This->lpOutFormat->biBitCount <= 8)
ICDecompressGetPalette(This->hic, This->lpInFormat,
This->lpOutFormat);
}
}
/* read input frame */
while (FAILED(AVIStreamRead(This->pStream, lNext, 1, This->lpInBuffer,
This->cbInBuffer, &readBytes, &readSamples))) {
/* not enough memory for input buffer? */
readBytes = 0;
if (FAILED(AVIStreamSampleSize(This->pStream, lNext, &readBytes)))
return NULL; /* bad thing, but bad things will happen */
if (readBytes <= 0) {
ERR(": IAVIStream::REad doesn't return needed bytes!\n");
return NULL;
}
/* IAVIStream::Read failed because of other reasons not buffersize? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -