HRESULT CCINVideoDecompressor::DecideBufferSize( IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties ) { CAutoLock lock(m_pLock); ASSERT(pAlloc); ASSERT(pProperties); // Check if we have the input pin and it's connected. // Otherwise there's no way to proceed any further if ( (m_pInput == NULL) || (!m_pInput->IsConnected()) ) return E_UNEXPECTED; // At this time we should have the format block if (!m_pFormat) return E_UNEXPECTED; // Get the input pin's allocator IMemAllocator *pInputAlloc = NULL; HRESULT hr = m_pInput->GetAllocator(&pInputAlloc); if (FAILED(hr)) return hr; // Get the input pin's allocator properties ALLOCATOR_PROPERTIES apInput; hr = pInputAlloc->GetProperties(&apInput); if (FAILED(hr)) { pInputAlloc->Release(); return hr; } // Release the input pin's allocator pInputAlloc->Release(); // Set the properties: output buffer's size is frame size, // the buffers amount is the same as for the input pin and // we don't care about alignment and prefix LONG cbFrame = m_pFormat->dwVideoWidth * m_pFormat->dwVideoHeight; pProperties->cbBuffer = max(pProperties->cbBuffer, cbFrame); pProperties->cBuffers = max(pProperties->cBuffers, apInput.cBuffers); ALLOCATOR_PROPERTIES apActual; hr = pAlloc->SetProperties(pProperties, &apActual); if (FAILED(hr)) return hr; // Check if the allocator is suitable return ( (apActual.cBuffers < pProperties->cBuffers) || (apActual.cbBuffer < pProperties->cbBuffer) ) ? E_FAIL : NOERROR; }
HRESULT CMVEADPCMDecompressor::DecideBufferSize( IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties ) { CAutoLock lock(m_pLock); ASSERT(pAlloc); ASSERT(pProperties); // Check if we have the input pin and it's connected. // Otherwise there's no way to proceed any further if ( (m_pInput == NULL) || (!m_pInput->IsConnected()) ) return E_UNEXPECTED; // Get the input pin's allocator IMemAllocator *pInputAlloc = NULL; HRESULT hr = m_pInput->GetAllocator(&pInputAlloc); if (FAILED(hr)) return hr; // Get the input pin's allocator properties ALLOCATOR_PROPERTIES apInput; hr = pInputAlloc->GetProperties(&apInput); if (FAILED(hr)) { pInputAlloc->Release(); return hr; } // Release the input pin's allocator pInputAlloc->Release(); // Set the properties: output buffer is two times larger // then the input one, the buffers amount is the same and // we don't care about alignment and prefix pProperties->cbBuffer = max(pProperties->cbBuffer, apInput.cbBuffer * 2); pProperties->cBuffers = max(pProperties->cBuffers, apInput.cBuffers); ALLOCATOR_PROPERTIES apActual; hr = pAlloc->SetProperties(pProperties, &apActual); if (FAILED(hr)) return hr; // Check if the allocator is suitable return ( (apActual.cBuffers < pProperties->cBuffers) || (apActual.cbBuffer < pProperties->cbBuffer) ) ? E_FAIL : NOERROR; }
HRESULT CCorePNGSubtitlerFilter::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) { HRESULT hr = NOERROR; // Is the input pin connected if(m_pInput->IsConnected() == FALSE) { return E_UNEXPECTED; } CheckPointer(pAlloc, E_POINTER); CheckPointer(ppropInputRequest, E_POINTER); ppropInputRequest->cBuffers = 1; ppropInputRequest->cbAlign = 1; // Get input pin's allocator size and use that ALLOCATOR_PROPERTIES InProps; IMemAllocator *pInAlloc = NULL; hr = m_pInput->GetAllocator(&pInAlloc); if(SUCCEEDED(hr)) { hr = pInAlloc->GetProperties(&InProps); if(SUCCEEDED(hr)) { ppropInputRequest->cbBuffer = InProps.cbBuffer * InProps.cBuffers; m_BufferSize = ppropInputRequest->cbBuffer; } pInAlloc->Release(); } if(FAILED(hr)) return hr; ASSERT(ppropInputRequest->cbBuffer); // Ask the allocator to reserve us some sample memory, NOTE the function // can succeed (that is return NOERROR) but still not have allocated the // memory that we requested, so we must check we got whatever we wanted ALLOCATOR_PROPERTIES Actual; hr = pAlloc->SetProperties(ppropInputRequest, &Actual); if(FAILED(hr)) { return hr; } ASSERT(Actual.cBuffers == 1); if(ppropInputRequest->cBuffers > Actual.cBuffers || ppropInputRequest->cbBuffer > Actual.cbBuffer) { return E_FAIL; } return NOERROR; };
/////////////////////////////////////////////////////////////////////// // DecideBufferSize: Tell the output pin's allocator what size buffers // we require. Can only do this when the input is connected /////////////////////////////////////////////////////////////////////// HRESULT CAACSBREnhanced::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties) { // Is the input pin connected if (m_pInput->IsConnected() == FALSE) { return E_UNEXPECTED; } ASSERT(pAlloc); ASSERT(pProperties); HRESULT hr = NOERROR; pProperties->cBuffers = 1; // Get input pin's allocator size and use that ALLOCATOR_PROPERTIES InProps; IMemAllocator * pInAlloc = NULL; hr = m_pInput->GetAllocator(&pInAlloc); if (SUCCEEDED (hr)) { hr = pInAlloc->GetProperties (&InProps); if (SUCCEEDED (hr)) { pProperties->cbBuffer = 8*1024; } pInAlloc->Release(); } if (FAILED(hr)) return hr; ASSERT(pProperties->cbBuffer); // Ask the allocator to reserve us some sample memory, NOTE the function // can succeed (that is return NOERROR) but still not have allocated the // memory that we requested, so we must check we got whatever we wanted ALLOCATOR_PROPERTIES Actual; hr = pAlloc->SetProperties(pProperties,&Actual); if (FAILED(hr)) { return hr; } ASSERT( Actual.cBuffers == 1 ); if ( pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer) { return E_FAIL; } return NOERROR; }
// we need to return an addref'ed allocator, even if it is the preferred // one, since he doesn't know whether it is the preferred one or not. STDMETHODIMP CAsyncOutputPin::RequestAllocator( IMemAllocator* pPreferred, ALLOCATOR_PROPERTIES* pProps, IMemAllocator ** ppActual) { CheckPointer(pProps, E_POINTER); ASSERT(m_pIo); // we care about alignment but nothing else if (!pProps->cbAlign || !m_pIo->IsAligned(pProps->cbAlign)) m_pIo->Alignment(&pProps->cbAlign); ALLOCATOR_PROPERTIES Actual; HRESULT hr; if (pPreferred) { hr = pPreferred->SetProperties(pProps, &Actual); if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) { pPreferred->AddRef(); *ppActual = pPreferred; return S_OK; } } // create our own allocator IMemAllocator* pAlloc; hr = InitAllocator(&pAlloc); if (FAILED(hr)) return hr; //...and see if we can make it suitable hr = pAlloc->SetProperties(pProps, &Actual); if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) { // we need to release our refcount on pAlloc, and addref // it to pass a refcount to the caller - this is a net nothing. *ppActual = pAlloc; return S_OK; } // failed to find a suitable allocator pAlloc->Release(); // if we failed because of the IsAligned test, the error code will // not be failure if (SUCCEEDED(hr)) hr = VFW_E_BADALIGN; return hr; }
HRESULT CG729EncoderFilter::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties) { HRESULT hr = NOERROR; if ( ! m_pInput->IsConnected() ) return E_UNEXPECTED; CheckPointer( pAlloc, E_POINTER ); CheckPointer( pProperties, E_POINTER ); pProperties->cBuffers = 1; // pProperties->cbAlign = 1; pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize(); ALLOCATOR_PROPERTIES InProps; IMemAllocator * pInAlloc = NULL; hr = m_pInput->GetAllocator(&pInAlloc); if(SUCCEEDED(hr)) { hr = pInAlloc->GetProperties(&InProps); if ( SUCCEEDED(hr) ) { pProperties->cbBuffer = InProps.cbBuffer; } pInAlloc->Release(); } if ( FAILED(hr) ) return hr; ASSERT( pProperties->cbBuffer ); ALLOCATOR_PROPERTIES Actual; hr = pAlloc->SetProperties(pProperties,&Actual); if ( FAILED(hr) ) return hr; ASSERT( Actual.cBuffers == 1 ); if (pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer) { return E_FAIL; } return NOERROR; }
STDMETHODIMP CTransInPlaceInputPin::NotifyAllocator( IMemAllocator * pAllocator, BOOL bReadOnly) { HRESULT hr = S_OK; CheckPointer(pAllocator,E_POINTER); ValidateReadPtr(pAllocator,sizeof(IMemAllocator)); CAutoLock cObjectLock(m_pLock); m_bReadOnly = bReadOnly; // If we modify data then don't accept the allocator if it's // the same as the output pin's allocator // If our output is not connected just accept the allocator // We're never going to use this allocator because when our // output pin is connected we'll reconnect this pin if (!m_pTIPFilter->OutputPin()->IsConnected()) { return CTransformInputPin::NotifyAllocator(pAllocator, bReadOnly); } // If the allocator is read-only and we're modifying data // and the allocator is the same as the output pin's // then reject if (bReadOnly && m_pTIPFilter->m_bModifiesData) { IMemAllocator *pOutputAllocator = m_pTIPFilter->OutputPin()->PeekAllocator(); // Make sure we have an output allocator if (pOutputAllocator == NULL) { hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()-> GetAllocator(&pOutputAllocator); if(FAILED(hr)) { hr = CreateMemoryAllocator(&pOutputAllocator); } if (SUCCEEDED(hr)) { m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator); pOutputAllocator->Release(); } } if (pAllocator == pOutputAllocator) { hr = E_FAIL; } else if(SUCCEEDED(hr)) { // Must copy so set the allocator properties on the output ALLOCATOR_PROPERTIES Props, Actual; hr = pAllocator->GetProperties(&Props); if (SUCCEEDED(hr)) { hr = pOutputAllocator->SetProperties(&Props, &Actual); } if (SUCCEEDED(hr)) { if ( (Props.cBuffers > Actual.cBuffers) || (Props.cbBuffer > Actual.cbBuffer) || (Props.cbAlign > Actual.cbAlign) ) { hr = E_FAIL; } } // Set the allocator on the output pin if (SUCCEEDED(hr)) { hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() ->NotifyAllocator( pOutputAllocator, FALSE ); } } } else { hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() ->NotifyAllocator( pAllocator, bReadOnly ); if (SUCCEEDED(hr)) { m_pTIPFilter->OutputPin()->SetAllocator( pAllocator ); } } if (SUCCEEDED(hr)) { // It's possible that the old and the new are the same thing. // AddRef before release ensures that we don't unload it. pAllocator->AddRef(); if( m_pAllocator != NULL ) m_pAllocator->Release(); m_pAllocator = pAllocator; // We have an allocator for the input pin } return hr; } // NotifyAllocator
STDMETHODIMP CRFSOutputPin::RequestAllocator (IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual) { if (!(pPreferred && pProps && ppActual)) return E_POINTER; ALLOCATOR_PROPERTIES actual; HRESULT hr; DbgLog((LOG_TRACE, 2, L"Requested alignment = %ld", pProps->cbAlign)); if (pProps->cbAlign) m_align = pProps->cbAlign; else pProps->cbAlign = m_align; if (pPreferred) { hr = pPreferred->SetProperties (pProps, &actual); if (SUCCEEDED (hr) && IsAligned (actual.cbAlign)) { DbgLog((LOG_TRACE, 2, L"Using preferred allocator.")); pPreferred->AddRef (); *ppActual = pPreferred; return S_OK; } } CMemAllocator *pMemObject = new CMemAllocator (L"RFS memory allocator", NULL, &hr); if (!pMemObject) return E_OUTOFMEMORY; if (FAILED (hr)) { delete pMemObject; return hr; } IMemAllocator* pAlloc; hr = pMemObject->QueryInterface (IID_IMemAllocator, (void **) &pAlloc); if (FAILED (hr)) { delete pMemObject; return E_NOINTERFACE; } hr = pAlloc->SetProperties (pProps, &actual); if (SUCCEEDED (hr) && IsAligned (actual.cbAlign)) { DbgLog((LOG_TRACE, 2, L"Using our allocator.")); *ppActual = pAlloc; return S_OK; } pAlloc->Release (); if (SUCCEEDED (hr)) hr = VFW_E_BADALIGN; DbgLog((LOG_TRACE, 2, L"RequestAllocator failed.")); return hr; }
HRESULT CAudioDecFilter::ReconnectOutput(long BufferSize, const CMediaType &mt) { HRESULT hr; IPin *pPin = m_pOutput->GetConnected(); if (pPin == NULL) return E_POINTER; IMemInputPin *pMemInputPin = NULL; hr = pPin->QueryInterface(IID_IMemInputPin, pointer_cast<void**>(&pMemInputPin)); if (FAILED(hr)) { OutputLog(TEXT("IMemInputPinインターフェースが取得できません。(%08x)\r\n"), hr); } else { IMemAllocator *pAllocator = NULL; hr = pMemInputPin->GetAllocator(&pAllocator); if (FAILED(hr)) { OutputLog(TEXT("IMemAllocatorインターフェースが取得できません。(%08x)\r\n"), hr); } else { ALLOCATOR_PROPERTIES Props; hr = pAllocator->GetProperties(&Props); if (FAILED(hr)) { OutputLog(TEXT("IMemAllocatorのプロパティが取得できません。(%08x)\r\n"), hr); } else { if (mt != m_pOutput->CurrentMediaType() || Props.cBuffers < NUM_SAMPLE_BUFFERS || Props.cbBuffer < BufferSize) { hr = S_OK; if (Props.cBuffers < NUM_SAMPLE_BUFFERS || Props.cbBuffer < BufferSize) { ALLOCATOR_PROPERTIES ActualProps; Props.cBuffers = NUM_SAMPLE_BUFFERS; Props.cbBuffer = BufferSize * 3 / 2; OutputLog(TEXT("バッファサイズを設定します。(%ld bytes)\r\n"), Props.cbBuffer); if (SUCCEEDED(hr = m_pOutput->DeliverBeginFlush()) && SUCCEEDED(hr = m_pOutput->DeliverEndFlush()) && SUCCEEDED(hr = pAllocator->Decommit()) && SUCCEEDED(hr = pAllocator->SetProperties(&Props, &ActualProps)) && SUCCEEDED(hr = pAllocator->Commit())) { if (ActualProps.cBuffers < Props.cBuffers || ActualProps.cbBuffer < BufferSize) { OutputLog(TEXT("バッファサイズの要求が受け付けられません。(%ld / %ld)\r\n"), ActualProps.cbBuffer, Props.cbBuffer); hr = E_FAIL; NotifyEvent(EC_ERRORABORT, hr, 0); } else { OutputLog(TEXT("ピンの再接続成功\r\n")); hr = S_OK; } } else { OutputLog(TEXT("ピンの再接続ができません。(%08x)\r\n"), hr); } } } else { hr = S_FALSE; } } pAllocator->Release(); } pMemInputPin->Release(); } return hr; }