#include #include "allocator.h" #include #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; iprops.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::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::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::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; }