static HRESULT STDCALL MemAllocator_GetBuffer(IMemAllocator * This, /* [out] */ IMediaSample **ppBuffer, /* [in] */ REFERENCE_TIME *pStartTime, /* [in] */ REFERENCE_TIME *pEndTime, /* [in] */ DWORD dwFlags) { MemAllocator* me = (MemAllocator*)This; CMediaSample* sample; Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This, avm_list_size(me->used_list), avm_list_size(me->free_list)); if (!me->free_list) { Debug printf("No samples available\n"); return E_FAIL;//should block here if no samples are available } sample = (CMediaSample*) me->free_list->member; me->free_list = avm_list_del_head(me->free_list); me->used_list = avm_list_add_tail(me->used_list, sample); *ppBuffer = (IMediaSample*) sample; sample->vt->AddRef((IUnknown*) sample); if (me->new_pointer) { if (me->modified_sample) me->modified_sample->ResetPointer(me->modified_sample); sample->SetPointer(sample, me->new_pointer); me->modified_sample = sample; me->new_pointer = 0; } return 0; }
//------------------------------------------------------------------------------ // IDecklinkPushSource2 interface //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // GetFrameBuffer // Provide the caller with a free media sample. If there are no free samples, // all have been delivered downstream, block until one is returned to the free list. STDMETHODIMP CCustomAllocator::GetFrameBuffer(IMediaSample** ppSample) { HRESULT hr = S_OK; if (ppSample) { CAutoLock lck(this); unsigned char* pBuffer = m_lBuffers.RemoveHead(); // retrieve a frame buffer if (pBuffer) { // attempt to retrieve a free media sample CMediaSample* pSample = NULL; for (;;) { { // scope for lock CAutoLock cObjectLock(this); /* Check we are committed */ if (!m_bCommitted) { return VFW_E_NOT_COMMITTED; } pSample = (CMediaSample*)m_lFree.RemoveHead(); if (pSample == NULL) { SetWaitingFree(); } } if (pSample) { // return the sample to the caller hr = pSample->SetPointer(pBuffer, m_lSize); *ppSample = pSample; break; } /* If we didn't get a sample then wait for the list to signal */ ASSERT(m_hSemFree); WaitForSingleObject(m_hSemFree, INFINITE); } } else { hr = E_FAIL; } } else { hr = E_POINTER; } return hr; }
//------------------------------------------------------------------------------ // Deliver // Attach the supplied buffer to a free media sample. Add media sample to delivery // queue so that the streaming thread can deliver the sample downstream. If there // are no free samples, all have been delivered downstream, block until one is returned // to the free list. If the streaming thread is blocked, waiting for a sample to // become available on the delivery queue, signal the thread when a new sample is added. STDMETHODIMP CCustomAllocator::Deliver(unsigned char* pBuffer) { HRESULT hr = S_OK; if (pBuffer) { CMediaSample* pSample = NULL; for (;;) { { // scope for lock CAutoLock cObjectLock(this); /* Check we are committed */ if (!m_bCommitted) { return VFW_E_NOT_COMMITTED; } pSample = (CMediaSample*)m_lFree.RemoveHead(); if (pSample == NULL) { SetWaitingFree(); } } if (pSample) { hr = pSample->SetPointer(pBuffer, m_lSize); if (SUCCEEDED(hr)) { CAutoLock cObjectLock(this); m_lDeliver.AddTail(pSample); NotifySample(); DbgLog((LOG_TRACE, DBG_MEM, TEXT("CCustomAllocator::Deliver(): m_lFree: %d m_lDeliver: %d"), m_lFree.GetCount(), m_lDeliver.GetCount())); } break; } /* If we didn't get a sample then wait for the list to signal */ ASSERT(m_hSemFree); WaitForSingleObject(m_hSemFree, INFINITE); } } else { hr = E_POINTER; } return hr; }