#include "allocator.h" #include #include #include //#undef Debug //#define Debug using namespace std; class AllocatorKeeper { public: AllocatorKeeper() { RegisterComClass(&CLSID_MemoryAllocator, MemAllocator::CreateAllocator); } ~AllocatorKeeper() { UnregisterComClass(&CLSID_MemoryAllocator, MemAllocator::CreateAllocator); } }; static AllocatorKeeper keeper; GUID MemAllocator::interfaces[]= { IID_IUnknown, IID_IMemAllocator, }; IMPLEMENT_IUNKNOWN(MemAllocator) 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; } static HRESULT STDCALL MemAllocator_SetProperties(IMemAllocator * This, /* [in] */ ALLOCATOR_PROPERTIES *pRequest, /* [out] */ ALLOCATOR_PROPERTIES *pActual) { Debug printf("MemAllocator_SetProperties() called\n"); if (!pRequest || !pActual) return E_INVALIDARG; if (pRequest->cBuffers<=0 || pRequest->cbBuffer<=0) return E_FAIL; MemAllocator* me = (MemAllocator*)This; if (me->used_list.size() || me->free_list.size()) return E_FAIL; me->props = *pRequest; *pActual = *pRequest; return 0; } static HRESULT STDCALL MemAllocator_GetProperties(IMemAllocator * This, /* [out] */ ALLOCATOR_PROPERTIES *pProps) { Debug printf("MemAllocator_GetProperties(%p) called\n", This); if (!pProps) return E_INVALIDARG; if (((MemAllocator*)This)->props.cbBuffer<0) return E_FAIL; *pProps=((MemAllocator*)This)->props; return 0; } static HRESULT STDCALL MemAllocator_Commit(IMemAllocator * This) { Debug printf("MemAllocator_Commit(%p) called\n", This); MemAllocator* me=(MemAllocator*)This; if (((MemAllocator*)This)->props.cbBuffer < 0) return E_FAIL; if (me->used_list.size() || me->free_list.size()) return E_INVALIDARG; for(int i = 0; iprops.cBuffers; i++) me->free_list.push_back(new CMediaSample(me, me->props.cbBuffer)); return 0; } static HRESULT STDCALL MemAllocator_Decommit(IMemAllocator * This) { Debug printf("MemAllocator_Decommit(%p) called\n", This); 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; } static HRESULT STDCALL MemAllocator_GetBuffer(IMemAllocator * This, /* [out] */ IMediaSample **ppBuffer, /* [in] */ REFERENCE_TIME *pStartTime, /* [in] */ REFERENCE_TIME *pEndTime, /* [in] */ DWORD dwFlags) { Debug printf("MemAllocator_GetBuffer(%p) called\n", This); MemAllocator* me = (MemAllocator*)This; if (me->free_list.size() == 0) { Debug printf("No samples available\n"); return E_FAIL;//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); if (me->new_pointer) { if(me->modified_sample) me->modified_sample->ResetPointer(); (*it)->SetPointer(me->new_pointer); me->modified_sample=*it; me->new_pointer = 0; } me->free_list.remove(*it); return 0; } static HRESULT STDCALL MemAllocator_ReleaseBuffer(IMemAllocator * This, /* [in] */ IMediaSample *pBuffer) { Debug printf("MemAllocator_ReleaseBuffer(%p) 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 E_FAIL; } MemAllocator::MemAllocator() { Debug printf("MemAllocator::MemAllocator() called\n"); vt = new IMemAllocator_vt; vt->QueryInterface = QueryInterface; vt->AddRef = AddRef; vt->Release = Release; vt->SetProperties = MemAllocator_SetProperties; vt->GetProperties = MemAllocator_GetProperties; vt->Commit = MemAllocator_Commit; vt->Decommit = MemAllocator_Decommit; vt->GetBuffer = MemAllocator_GetBuffer; vt->ReleaseBuffer = MemAllocator_ReleaseBuffer; refcount = 1; props.cBuffers = 1; props.cbBuffer = 65536; /* :/ */ props.cbAlign = props.cbPrefix = 0; new_pointer=0; modified_sample=0; } MemAllocator::~MemAllocator() { Debug printf("MemAllocator::~MemAllocator() called\n"); delete vt; }