diff options
Diffstat (limited to 'loader/dshow/allocator.c')
-rw-r--r-- | loader/dshow/allocator.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/loader/dshow/allocator.c b/loader/dshow/allocator.c new file mode 100644 index 0000000000..496d56c66f --- /dev/null +++ b/loader/dshow/allocator.c @@ -0,0 +1,154 @@ +#include <stdio.h> +#include "allocator.h" +#include <com.h> +#define E_NOTIMPL 0x80004001 +class AllocatorKeeper +{ +public: + AllocatorKeeper() + { + RegisterComClass(&CLSID_MemoryAllocator, MemAllocator::CreateAllocator); + } +}; +static AllocatorKeeper keeper; +GUID MemAllocator::interfaces[]= +{ + IID_IUnknown, + IID_IMemAllocator, +}; +IMPLEMENT_IUNKNOWN(MemAllocator) + +MemAllocator::MemAllocator() + :refcount(1) +{ + Debug printf("MemAllocator::MemAllocator() called\n"); + vt=new IMemAllocator_vt; + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->SetProperties = SetProperties; + vt->GetProperties = GetProperties; + vt->Commit = Commit; + vt->Decommit = Decommit; + vt->GetBuffer = GetBuffer; + vt->ReleaseBuffer = ReleaseBuffer; + + props.cBuffers=1; + props.cbBuffer=65536;/* :/ */ + props.cbAlign=props.cbPrefix=0; +} + +long MemAllocator::CreateAllocator(GUID* clsid, GUID* iid, void** ppv) +{ + if(!ppv)return -1; + *ppv=0; + if(memcmp(clsid, &CLSID_MemoryAllocator, sizeof(GUID))) + return -1; + + IMemAllocator* p=new MemAllocator; + int result=p->vt->QueryInterface((IUnknown*)p, iid, ppv); + p->vt->Release((IUnknown*)p); + return result; +} + + +/* + long cBuffers; + long cbBuffer; + long cbAlign; + long cbPrefix; +*/ +HRESULT STDCALL MemAllocator::SetProperties ( + IMemAllocator * This, + /* [in] */ ALLOCATOR_PROPERTIES *pRequest, + /* [out] */ ALLOCATOR_PROPERTIES *pActual) +{ + Debug printf("MemAllocator::SetProperties() called\n"); + if(!pRequest)return 0x80004003; + if(!pActual)return 0x80004003; + if(pRequest->cBuffers<=0)return -1; + if(pRequest->cbBuffer<=0)return -1; + MemAllocator* me=(MemAllocator*)This; + if(me->used_list.size() || me->free_list.size())return -1; + me->props=*pRequest; + *pActual=*pRequest; + return 0; +} + +HRESULT STDCALL MemAllocator::GetProperties ( + IMemAllocator * This, + /* [out] */ ALLOCATOR_PROPERTIES *pProps) +{ + Debug printf("MemAllocator::GetProperties() called\n"); + if(!pProps)return -1; + if(((MemAllocator*)This)->props.cbBuffer<0)return -1; + *pProps=((MemAllocator*)This)->props; + return 0; +} + +HRESULT STDCALL MemAllocator::Commit ( + IMemAllocator * This) +{ + Debug printf("MemAllocator::Commit() called\n"); + MemAllocator* me=(MemAllocator*)This; + if(((MemAllocator*)This)->props.cbBuffer<0)return -1; + if(me->used_list.size() || me->free_list.size())return -1; + for(int i=0; i<me->props.cBuffers; i++) + me->free_list.push_back(new CMediaSample(me, me->props.cbBuffer)); + return 0; +} + +HRESULT STDCALL MemAllocator::Decommit ( + IMemAllocator * This) +{ + Debug printf("MemAllocator::Decommit() called\n"); + MemAllocator* me=(MemAllocator*)This; + list<CMediaSample*>::iterator it; + for(it=me->free_list.begin(); it!=me->free_list.end(); it++) + delete *it; + for(it=me->used_list.begin(); it!=me->used_list.end(); it++) + delete *it; + me->free_list.clear(); + me->used_list.clear(); + return 0; +} + +HRESULT STDCALL MemAllocator::GetBuffer ( + IMemAllocator * This, + /* [out] */ IMediaSample **ppBuffer, + /* [in] */ REFERENCE_TIME *pStartTime, + /* [in] */ REFERENCE_TIME *pEndTime, + /* [in] */ DWORD dwFlags) +{ + Debug printf("%x: MemAllocator::GetBuffer() called\n", This); + MemAllocator* me=(MemAllocator*)This; + if(me->free_list.size()==0) + { + Debug printf("No samples available\n"); + return -1;//should block here if no samples are available + } + list<CMediaSample*>::iterator it=me->free_list.begin(); + me->used_list.push_back(*it); + *ppBuffer=*it; + (*ppBuffer)->vt->AddRef((IUnknown*)*ppBuffer); + me->free_list.remove(*it); + return 0; +} + +HRESULT STDCALL MemAllocator::ReleaseBuffer ( + IMemAllocator * This, + /* [in] */ IMediaSample *pBuffer) +{ + Debug printf("%x: MemAllocator::ReleaseBuffer() called\n", This); + MemAllocator* me=(MemAllocator*)This; + list<CMediaSample*>::iterator it; + for(it=me->used_list.begin(); it!=me->used_list.end(); it++) + if(*it==pBuffer) + { + me->used_list.erase(it); + me->free_list.push_back((CMediaSample*)pBuffer); + return 0; + } + Debug printf("Releasing unknown buffer\n"); + return -1; +} |