quartz: Expose some methods so that a custom allocator can be created.

This commit is contained in:
Maarten Lankhorst 2008-06-10 18:06:08 +02:00 committed by Alexandre Julliard
parent 3a9040c1f2
commit 365bbe8343
2 changed files with 116 additions and 82 deletions

View File

@ -27,7 +27,6 @@
#include "vfwmsgs.h"
#include "quartz_private.h"
#include "wine/list.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
@ -51,35 +50,6 @@ void dump_AM_SAMPLE2_PROPERTIES(const AM_SAMPLE2_PROPERTIES * pProps)
TRACE("\tcbBuffer: %d\n", pProps->cbBuffer);
}
typedef struct BaseMemAllocator
{
const IMemAllocatorVtbl * lpVtbl;
LONG ref;
ALLOCATOR_PROPERTIES * pProps;
CRITICAL_SECTION csState;
HRESULT (* fnAlloc) (IMemAllocator *);
HRESULT (* fnFree)(IMemAllocator *);
HANDLE hSemWaiting;
BOOL bDecommitQueued;
BOOL bCommitted;
LONG lWaiting;
struct list free_list;
struct list used_list;
} BaseMemAllocator;
typedef struct StdMediaSample2
{
const IMediaSample2Vtbl * lpvtbl;
LONG ref;
AM_SAMPLE2_PROPERTIES props;
IMemAllocator * pParent;
struct list listentry;
LONGLONG tMediaStart;
LONGLONG tMediaEnd;
} StdMediaSample2;
static const IMemAllocatorVtbl BaseMemAllocator_VTable;
static const IMediaSample2Vtbl StdMediaSample2_VTable;
@ -87,25 +57,34 @@ static const IMediaSample2Vtbl StdMediaSample2_VTable;
#define INVALID_MEDIA_TIME (((ULONGLONG)0x7fffffff << 32) | 0xffffffff)
static HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *), HRESULT (* fnFree)(IMemAllocator *), BaseMemAllocator * pMemAlloc)
HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *),
HRESULT (* fnFree)(IMemAllocator *),
HRESULT (* fnVerify)(IMemAllocator *, ALLOCATOR_PROPERTIES *),
HRESULT (* fnBufferPrepare)(IMemAllocator *, StdMediaSample2 *, DWORD),
HRESULT (* fnBufferReleased)(IMemAllocator *, StdMediaSample2 *),
void (* fnDestroyed)(IMemAllocator *),
CRITICAL_SECTION *pCritSect,
BaseMemAllocator * pMemAlloc)
{
assert(fnAlloc && fnFree);
assert(fnAlloc && fnFree && fnDestroyed);
pMemAlloc->lpVtbl = &BaseMemAllocator_VTable;
pMemAlloc->ref = 1;
pMemAlloc->pProps = NULL;
ZeroMemory(&pMemAlloc->props, sizeof(pMemAlloc->props));
list_init(&pMemAlloc->free_list);
list_init(&pMemAlloc->used_list);
pMemAlloc->fnAlloc = fnAlloc;
pMemAlloc->fnFree = fnFree;
pMemAlloc->fnVerify = fnVerify;
pMemAlloc->fnBufferPrepare = fnBufferPrepare;
pMemAlloc->fnBufferReleased = fnBufferReleased;
pMemAlloc->fnDestroyed = fnDestroyed;
pMemAlloc->bDecommitQueued = FALSE;
pMemAlloc->bCommitted = FALSE;
pMemAlloc->hSemWaiting = NULL;
pMemAlloc->lWaiting = 0;
InitializeCriticalSection(&pMemAlloc->csState);
pMemAlloc->csState.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BaseMemAllocator.csState");
pMemAlloc->pCritSect = pCritSect;
return S_OK;
}
@ -155,10 +134,8 @@ static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface)
CloseHandle(This->hSemWaiting);
if (This->bCommitted)
This->fnFree(iface);
CoTaskMemFree(This->pProps);
This->csState.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csState);
CoTaskMemFree(This);
This->fnDestroyed(iface);
return 0;
}
return ref;
@ -171,7 +148,7 @@ static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLO
TRACE("(%p)->(%p, %p)\n", This, pRequest, pActual);
EnterCriticalSection(&This->csState);
EnterCriticalSection(This->pCritSect);
{
if (!list_empty(&This->used_list))
hr = VFW_E_BUFFERS_OUTSTANDING;
@ -181,22 +158,18 @@ static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLO
hr = VFW_E_BADALIGN;
else
{
if (!This->pProps)
This->pProps = CoTaskMemAlloc(sizeof(*This->pProps));
if (!This->pProps)
hr = E_OUTOFMEMORY;
if (This->fnVerify)
hr = This->fnVerify(iface, pRequest);
else
{
*This->pProps = *pRequest;
hr = S_OK;
*pActual = *pRequest;
if (SUCCEEDED(hr))
This->props = *pRequest;
hr = S_OK;
}
*pActual = This->props;
}
}
LeaveCriticalSection(&This->csState);
LeaveCriticalSection(This->pCritSect);
return hr;
}
@ -208,20 +181,11 @@ static HRESULT WINAPI BaseMemAllocator_GetProperties(IMemAllocator * iface, ALLO
TRACE("(%p)->(%p)\n", This, pProps);
EnterCriticalSection(&This->csState);
EnterCriticalSection(This->pCritSect);
{
/* NOTE: this is different from the native version.
* It would silently succeed if the properties had
* not been set, but would fail further on down the
* line with some obscure error like having an
* invalid alignment. Whether or not our version
* will cause any problems remains to be seen */
if (!This->pProps)
hr = VFW_E_SIZENOTSET;
else
memcpy(pProps, This->pProps, sizeof(*pProps));
memcpy(pProps, &This->props, sizeof(*pProps));
}
LeaveCriticalSection(&This->csState);
LeaveCriticalSection(This->pCritSect);
return hr;
}
@ -233,10 +197,14 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface)
TRACE("(%p)->()\n", This);
EnterCriticalSection(&This->csState);
EnterCriticalSection(This->pCritSect);
{
if (!This->pProps)
if (!This->props.cbAlign)
hr = VFW_E_BADALIGN;
else if (!This->props.cbBuffer)
hr = VFW_E_SIZENOTSET;
else if (!This->props.cBuffers)
hr = VFW_E_BUFFER_NOTSET;
else if (This->bDecommitQueued && This->bCommitted)
{
This->bDecommitQueued = FALSE;
@ -246,7 +214,7 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface)
hr = S_OK;
else
{
if (!(This->hSemWaiting = CreateSemaphoreW(NULL, This->pProps->cBuffers, This->pProps->cBuffers, NULL)))
if (!(This->hSemWaiting = CreateSemaphoreW(NULL, This->props.cBuffers, This->props.cBuffers, NULL)))
{
ERR("Couldn't create semaphore (error was %u)\n", GetLastError());
hr = HRESULT_FROM_WIN32(GetLastError());
@ -261,7 +229,7 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface)
}
}
}
LeaveCriticalSection(&This->csState);
LeaveCriticalSection(This->pCritSect);
return hr;
}
@ -273,7 +241,7 @@ static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface)
TRACE("(%p)->()\n", This);
EnterCriticalSection(&This->csState);
EnterCriticalSection(This->pCritSect);
{
if (!This->bCommitted)
hr = S_OK;
@ -301,7 +269,7 @@ static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface)
}
}
}
LeaveCriticalSection(&This->csState);
LeaveCriticalSection(This->pCritSect);
return hr;
}
@ -329,7 +297,7 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa
}
This->lWaiting--;
EnterCriticalSection(&This->csState);
EnterCriticalSection(This->pCritSect);
{
if (!This->bCommitted)
hr = VFW_E_NOT_COMMITTED;
@ -348,7 +316,7 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa
IMediaSample_AddRef(*pSample);
}
}
LeaveCriticalSection(&This->csState);
LeaveCriticalSection(This->pCritSect);
return hr;
}
@ -365,7 +333,7 @@ static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMed
/* FIXME: we should probably check the ref count on the sample before freeing
* it to make sure that it is not still in use */
EnterCriticalSection(&This->csState);
EnterCriticalSection(This->pCritSect);
{
if (!This->bCommitted)
ERR("Releasing a buffer when the allocator is not committed?!?\n");
@ -391,7 +359,7 @@ static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMed
ERR("fnFree failed with error 0x%x\n", hrfree);
}
}
LeaveCriticalSection(&This->csState);
LeaveCriticalSection(This->pCritSect);
/* notify a waiting thread that there is now a free buffer */
if (This->hSemWaiting && !ReleaseSemaphore(This->hSemWaiting, 1, NULL))
@ -416,7 +384,7 @@ static const IMemAllocatorVtbl BaseMemAllocator_VTable =
BaseMemAllocator_ReleaseBuffer
};
static HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAllocator * pParent, StdMediaSample2 ** ppSample)
HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAllocator * pParent, StdMediaSample2 ** ppSample)
{
assert(pbBuffer && pParent && (cbBuffer > 0));
@ -440,7 +408,7 @@ static HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAll
return S_OK;
}
static void StdMediaSample2_Delete(StdMediaSample2 * This)
void StdMediaSample2_Delete(StdMediaSample2 * This)
{
/* NOTE: does not remove itself from the list it belongs to */
CoTaskMemFree(This);
@ -507,6 +475,12 @@ static HRESULT WINAPI StdMediaSample2_GetPointer(IMediaSample2 * iface, BYTE **
*ppBuffer = This->props.pbBuffer;
if (!*ppBuffer)
{
ERR("Requested an unlocked surface and trying to lock regardless\n");
return E_FAIL;
}
return S_OK;
}
@ -782,6 +756,7 @@ static const IMediaSample2Vtbl StdMediaSample2_VTable =
typedef struct StdMemAllocator
{
BaseMemAllocator base;
CRITICAL_SECTION csState;
LPVOID pMemory;
} StdMemAllocator;
@ -798,21 +773,21 @@ static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface)
GetSystemInfo(&si);
/* we do not allow a courser alignment than the OS page size */
if ((si.dwPageSize % This->base.pProps->cbAlign) != 0)
if ((si.dwPageSize % This->base.props.cbAlign) != 0)
return VFW_E_BADALIGN;
/* FIXME: each sample has to have its buffer start on the right alignment.
* We don't do this at the moment */
/* allocate memory */
This->pMemory = VirtualAlloc(NULL, (This->base.pProps->cbBuffer + This->base.pProps->cbPrefix) * This->base.pProps->cBuffers, MEM_COMMIT, PAGE_READWRITE);
This->pMemory = VirtualAlloc(NULL, (This->base.props.cbBuffer + This->base.props.cbPrefix) * This->base.props.cBuffers, MEM_COMMIT, PAGE_READWRITE);
for (i = This->base.pProps->cBuffers - 1; i >= 0; i--)
for (i = This->base.props.cBuffers - 1; i >= 0; i--)
{
/* pbBuffer does not start at the base address, it starts at base + cbPrefix */
BYTE * pbBuffer = (BYTE *)This->pMemory + i * (This->base.pProps->cbBuffer + This->base.pProps->cbPrefix) + This->base.pProps->cbPrefix;
BYTE * pbBuffer = (BYTE *)This->pMemory + i * (This->base.props.cbBuffer + This->base.props.cbPrefix) + This->base.props.cbPrefix;
StdMediaSample2_Construct(pbBuffer, This->base.pProps->cbBuffer, iface, &pSample);
StdMediaSample2_Construct(pbBuffer, This->base.props.cbBuffer, iface, &pSample);
list_add_head(&This->base.free_list, &pSample->listentry);
}
@ -853,6 +828,16 @@ static HRESULT StdMemAllocator_Free(IMemAllocator * iface)
return S_OK;
}
static void StdMemAllocator_Destroy(IMemAllocator *iface)
{
StdMemAllocator *This = (StdMemAllocator *)iface;
This->csState.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csState);
CoTaskMemFree(This);
}
HRESULT StdMemAllocator_create(LPUNKNOWN lpUnkOuter, LPVOID * ppv)
{
StdMemAllocator * pMemAlloc;
@ -866,9 +851,12 @@ HRESULT StdMemAllocator_create(LPUNKNOWN lpUnkOuter, LPVOID * ppv)
if (!(pMemAlloc = CoTaskMemAlloc(sizeof(*pMemAlloc))))
return E_OUTOFMEMORY;
InitializeCriticalSection(&pMemAlloc->csState);
pMemAlloc->csState.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StdMemAllocator.csState");
pMemAlloc->pMemory = NULL;
if (SUCCEEDED(hr = BaseMemAllocator_Init(StdMemAllocator_Alloc, StdMemAllocator_Free, &pMemAlloc->base)))
if (SUCCEEDED(hr = BaseMemAllocator_Init(StdMemAllocator_Alloc, StdMemAllocator_Free, NULL, NULL, NULL, StdMemAllocator_Destroy, &pMemAlloc->csState, &pMemAlloc->base)))
*ppv = (LPVOID)pMemAlloc;
else
CoTaskMemFree(pMemAlloc);

View File

@ -33,6 +33,7 @@
#include "wingdi.h"
#include "winuser.h"
#include "dshow.h"
#include "wine/list.h"
#define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000)
#define SEC_FROM_MEDIATIME(time) ((time) / 10000000)
@ -84,4 +85,49 @@ BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, B
void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt);
HRESULT updatehres( HRESULT original, HRESULT new );
typedef struct StdMediaSample2
{
const IMediaSample2Vtbl * lpvtbl;
LONG ref;
AM_SAMPLE2_PROPERTIES props;
IMemAllocator * pParent;
struct list listentry;
LONGLONG tMediaStart;
LONGLONG tMediaEnd;
} StdMediaSample2;
typedef struct BaseMemAllocator
{
const IMemAllocatorVtbl * lpVtbl;
LONG ref;
ALLOCATOR_PROPERTIES props;
HRESULT (* fnAlloc) (IMemAllocator *);
HRESULT (* fnFree)(IMemAllocator *);
HRESULT (* fnVerify)(IMemAllocator *, ALLOCATOR_PROPERTIES *);
HRESULT (* fnBufferPrepare)(IMemAllocator *, StdMediaSample2 *, DWORD flags);
HRESULT (* fnBufferReleased)(IMemAllocator *, StdMediaSample2 *);
void (* fnDestroyed)(IMemAllocator *);
HANDLE hSemWaiting;
BOOL bDecommitQueued;
BOOL bCommitted;
LONG lWaiting;
struct list free_list;
struct list used_list;
CRITICAL_SECTION *pCritSect;
} BaseMemAllocator;
HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *),
HRESULT (* fnFree)(IMemAllocator *),
HRESULT (* fnVerify)(IMemAllocator *, ALLOCATOR_PROPERTIES *),
HRESULT (* fnBufferPrepare)(IMemAllocator *, StdMediaSample2 *, DWORD),
HRESULT (* fnBufferReleased)(IMemAllocator *, StdMediaSample2 *),
void (* fnDestroyed)(IMemAllocator *),
CRITICAL_SECTION *pCritSect,
BaseMemAllocator * pMemAlloc);
HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAllocator * pParent, StdMediaSample2 ** ppSample);
void StdMediaSample2_Delete(StdMediaSample2 * This);
#endif /* __QUARTZ_PRIVATE_INCLUDED__ */