static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual) { BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr; TRACE("(%p)->(%p, %p)\n", This, pRequest, pActual); EnterCriticalSection(This->pCritSect); { if (!list_empty(&This->used_list)) hr = VFW_E_BUFFERS_OUTSTANDING; else if (This->bCommitted) hr = VFW_E_ALREADY_COMMITTED; else if (pRequest->cbAlign == 0) hr = VFW_E_BADALIGN; else { if (This->fnVerify) hr = This->fnVerify(iface, pRequest); else hr = S_OK; if (SUCCEEDED(hr)) This->props = *pRequest; *pActual = This->props; } } LeaveCriticalSection(This->pCritSect); return hr; }
static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMediaSample * pSample) { BaseMemAllocator *This = impl_from_IMemAllocator(iface); StdMediaSample2 * pStdSample = unsafe_impl_from_IMediaSample(pSample); HRESULT hr = S_OK; TRACE("(%p)->(%p)\n", This, pSample); /* FIXME: make sure that sample is currently on the used list */ /* 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->pCritSect); { if (!This->bCommitted) ERR("Releasing a buffer when the allocator is not committed?!?\n"); /* remove from used_list */ list_remove(&pStdSample->listentry); list_add_head(&This->free_list, &pStdSample->listentry); if (list_empty(&This->used_list) && This->bDecommitQueued && This->bCommitted) { HRESULT hrfree; if (This->lWaiting != 0) ERR("Waiting: %d\n", This->lWaiting); This->bCommitted = FALSE; This->bDecommitQueued = FALSE; CloseHandle(This->hSemWaiting); This->hSemWaiting = NULL; if (FAILED(hrfree = This->fnFree(iface))) ERR("fnFree failed with error 0x%x\n", hrfree); } } LeaveCriticalSection(This->pCritSect); /* notify a waiting thread that there is now a free buffer */ if (This->hSemWaiting && !ReleaseSemaphore(This->hSemWaiting, 1, NULL)) { ERR("ReleaseSemaphore failed with error %u\n", GetLastError()); hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; }
static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface) { BaseMemAllocator *This = (BaseMemAllocator *)iface; ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->() Release from %ld\n", iface, ref + 1); if (!ref) { CloseHandle(This->hSemWaiting); if (This->bCommitted) This->fnFree(iface); HeapFree(GetProcessHeap(), 0, This->pProps); CoTaskMemFree(This); return 0; } return ref; }
static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface) { BaseMemAllocator *This = impl_from_IMemAllocator(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->() Release from %d\n", iface, ref + 1); if (!ref) { CloseHandle(This->hSemWaiting); if (This->bCommitted) This->fnFree(iface); This->fnDestroyed(iface); return 0; } return ref; }
static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface) { BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr; TRACE("(%p)->()\n", This); EnterCriticalSection(This->pCritSect); { 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; hr = S_OK; } else if (This->bCommitted) hr = S_OK; else { 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()); } else { hr = This->fnAlloc(iface); if (SUCCEEDED(hr)) This->bCommitted = TRUE; else ERR("fnAlloc failed with error 0x%x\n", hr); } } } LeaveCriticalSection(This->pCritSect); return hr; }
static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface) { BaseMemAllocator *This = (BaseMemAllocator *)iface; ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->() Release from %d\n", iface, ref + 1); if (!ref) { CloseHandle(This->hSemWaiting); if (This->bCommitted) This->fnFree(iface); CoTaskMemFree(This->pProps); This->csState.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->csState); CoTaskMemFree(This); return 0; } return ref; }
static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface) { BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr; TRACE("(%p)->()\n", This); EnterCriticalSection(This->pCritSect); { if (!This->bCommitted) hr = S_OK; else { if (!list_empty(&This->used_list)) { This->bDecommitQueued = TRUE; /* notify ALL waiting threads that they cannot be allocated a buffer any more */ ReleaseSemaphore(This->hSemWaiting, This->lWaiting, NULL); hr = S_OK; } else { if (This->lWaiting != 0) ERR("Waiting: %d\n", This->lWaiting); This->bCommitted = FALSE; CloseHandle(This->hSemWaiting); This->hSemWaiting = NULL; hr = This->fnFree(iface); if (FAILED(hr)) ERR("fnFree failed with error 0x%x\n", hr); } } } LeaveCriticalSection(This->pCritSect); return hr; }
static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface) { BaseMemAllocator *This = (BaseMemAllocator *)iface; HRESULT hr; TRACE("(%p)->()\n", This); EnterCriticalSection(&This->csState); { if (!This->pProps) hr = VFW_E_SIZENOTSET; else if (This->bCommitted) hr = S_OK; else if (This->bDecommitQueued) { This->bDecommitQueued = FALSE; hr = S_OK; } else { if (!(This->hSemWaiting = CreateSemaphoreW(NULL, This->pProps->cBuffers, This->pProps->cBuffers, NULL))) { ERR("Couldn't create semaphore (error was %ld)\n", GetLastError()); hr = HRESULT_FROM_WIN32(GetLastError()); } else { hr = This->fnAlloc(iface); if (SUCCEEDED(hr)) This->bCommitted = TRUE; else ERR("fnAlloc failed with error 0x%lx\n", hr); } } } LeaveCriticalSection(&This->csState); return hr; }