📄 grabber.cpp.svn-base
字号:
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabber::SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * m_pBuffer )
{
// have the input/output pins been created?
if( !InputPin( ) || !OutputPin( ) )
{
return E_POINTER;
}
// they can't be connected if we're going to be changing delivery buffers
//
if( InputPin( )->IsConnected( ) || OutputPin( )->IsConnected( ) )
{
return E_INVALIDARG;
}
return ((CSampleGrabberInPin*)m_pInput)->SetDeliveryBuffer( props, m_pBuffer );
}
//----------------------------------------------------------------------------
// used to help speed input pin connection times. We return a partially
// specified media type - only the main type is specified. If we return
// anything BUT a major type, some codecs written improperly will crash
//----------------------------------------------------------------------------
HRESULT CSampleGrabberInPin::GetMediaType( int iPosition, CMediaType * pMediaType )
{
CheckPointer(pMediaType,E_POINTER);
if (iPosition < 0) {
return E_INVALIDARG;
}
if (iPosition > 0) {
return VFW_S_NO_MORE_ITEMS;
}
*pMediaType = CMediaType( );
pMediaType->SetType( ((CSampleGrabber*)m_pFilter)->m_mtAccept.Type( ) );
return S_OK;
}
//----------------------------------------------------------------------------
// override the CTransInPlaceInputPin's method, and return a new enumerator
// if the input pin is disconnected. This will allow GetMediaType to be
// called. If we didn't do this, EnumMediaTypes returns a failure code
// and GetMediaType is never called.
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabberInPin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
{
CheckPointer(ppEnum,E_POINTER);
ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));
// if the output pin isn't connected yet, offer the possibly
// partially specified media type that has been set by the user
if( !((CSampleGrabber*)m_pTIPFilter)->OutputPin( )->IsConnected() )
{
// Create a new reference counted enumerator
*ppEnum = new CEnumMediaTypes( this, NULL );
return (*ppEnum) ? NOERROR : E_OUTOFMEMORY;
}
// if the output pin is connected, offer it's fully qualified media type
return ((CSampleGrabber*)m_pTIPFilter)->OutputPin( )->GetConnected()->EnumMediaTypes( ppEnum );
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabberInPin::NotifyAllocator( IMemAllocator *pAllocator, BOOL bReadOnly )
{
if( m_pPrivateAllocator )
{
if( pAllocator != m_pPrivateAllocator )
{
return E_FAIL;
}
else
{
// if the upstream guy wants to be read only and we don't, then that's bad
// if the upstream guy doesn't request read only, but we do, that's okay
if( bReadOnly && !SampleGrabber( )->IsReadOnly( ) )
{
return E_FAIL;
}
}
}
return CTransInPlaceInputPin::NotifyAllocator( pAllocator, bReadOnly );
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
STDMETHODIMP CSampleGrabberInPin::GetAllocator( IMemAllocator **ppAllocator )
{
if( m_pPrivateAllocator )
{
CheckPointer(ppAllocator,E_POINTER);
*ppAllocator = m_pPrivateAllocator;
m_pPrivateAllocator->AddRef( );
return NOERROR;
}
else
{
return CTransInPlaceInputPin::GetAllocator( ppAllocator );
}
}
//----------------------------------------------------------------------------
// GetAllocatorRequirements: The upstream filter calls this to get our
// filter's allocator requirements. If the app has set the buffer, then
// we return those props. Otherwise, we use the default TransInPlace behavior.
//----------------------------------------------------------------------------
HRESULT CSampleGrabberInPin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES *pProps )
{
CheckPointer(pProps,E_POINTER);
if (m_pPrivateAllocator)
{
*pProps = m_allocprops;
return S_OK;
}
else
{
return CTransInPlaceInputPin::GetAllocatorRequirements(pProps);
}
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
HRESULT CSampleGrabberInPin::SetDeliveryBuffer( ALLOCATOR_PROPERTIES props, BYTE * pBuffer )
{
// don't allow more than one buffer
if( props.cBuffers != 1 )
{
return E_INVALIDARG;
}
if( !pBuffer )
{
return E_POINTER;
}
m_allocprops = props;
m_pBuffer = pBuffer;
// If there is an existing allocator, make sure that it is released
// to prevent a memory leak
if (m_pPrivateAllocator)
{
m_pPrivateAllocator->Release();
m_pPrivateAllocator = NULL;
}
HRESULT hr = S_OK;
m_pPrivateAllocator = new CSampleGrabberAllocator( this, &hr );
if( !m_pPrivateAllocator )
{
return E_OUTOFMEMORY;
}
m_pPrivateAllocator->AddRef( );
return hr;
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
HRESULT CSampleGrabberInPin::SetMediaType( const CMediaType *pmt )
{
m_bMediaTypeChanged = TRUE;
return CTransInPlaceInputPin::SetMediaType( pmt );
}
//----------------------------------------------------------------------------
// don't allocate the memory, just use the buffer the app provided
//----------------------------------------------------------------------------
HRESULT CSampleGrabberAllocator::Alloc( )
{
// look at the base class code to see where this came from!
CAutoLock lck(this);
// Check he has called SetProperties
HRESULT hr = CBaseAllocator::Alloc();
if (FAILED(hr)) {
return hr;
}
// If the requirements haven't changed then don't reallocate
if (hr == S_FALSE) {
ASSERT(m_pBuffer);
return NOERROR;
}
ASSERT(hr == S_OK); // we use this fact in the loop below
// Free the old resources
if (m_pBuffer) {
ReallyFree();
}
// Compute the aligned size
LONG lAlignedSize = m_lSize + m_lPrefix;
if (m_lAlignment > 1)
{
LONG lRemainder = lAlignedSize % m_lAlignment;
if (lRemainder != 0)
{
lAlignedSize += (m_lAlignment - lRemainder);
}
}
// Create the contiguous memory block for the samples
// making sure it's properly aligned (64K should be enough!)
ASSERT(lAlignedSize % m_lAlignment == 0);
// don't create the buffer - use what was passed to us
//
m_pBuffer = m_pPin->m_pBuffer;
if (m_pBuffer == NULL) {
return E_OUTOFMEMORY;
}
LPBYTE pNext = m_pBuffer;
CMediaSample *pSample;
ASSERT(m_lAllocated == 0);
// Create the new samples - we have allocated m_lSize bytes for each sample
// plus m_lPrefix bytes per sample as a prefix. We set the pointer to
// the memory after the prefix - so that GetPointer() will return a pointer
// to m_lSize bytes.
for (; m_lAllocated < m_lCount; m_lAllocated++, pNext += lAlignedSize)
{
pSample = new CMediaSample(
NAME("Sample Grabber memory media sample"),
this,
&hr,
pNext + m_lPrefix, // GetPointer() value
m_lSize); // not including prefix
ASSERT(SUCCEEDED(hr));
if (pSample == NULL)
return E_OUTOFMEMORY;
// This CANNOT fail
m_lFree.Add(pSample);
}
m_bChanged = FALSE;
return NOERROR;
}
//----------------------------------------------------------------------------
// don't really free the memory
//----------------------------------------------------------------------------
void CSampleGrabberAllocator::ReallyFree()
{
// look at the base class code to see where this came from!
// Should never be deleting this unless all buffers are freed
ASSERT(m_lAllocated == m_lFree.GetCount());
// Free up all the CMediaSamples
CMediaSample *pSample;
for (;;)
{
pSample = m_lFree.RemoveHead();
if (pSample != NULL)
{
delete pSample;
}
else
{
break;
}
}
m_lAllocated = 0;
// don't free the buffer - let the app do it
}
//----------------------------------------------------------------------------
// SetProperties: Called by the upstream filter to set the allocator
// properties. The application has already allocated the buffer, so we reject
// anything that is not compatible with that, and return the actual props.
//----------------------------------------------------------------------------
HRESULT CSampleGrabberAllocator::SetProperties(
ALLOCATOR_PROPERTIES *pRequest,
ALLOCATOR_PROPERTIES *pActual
)
{
HRESULT hr = CMemAllocator::SetProperties(pRequest, pActual);
if (FAILED(hr))
{
return hr;
}
ALLOCATOR_PROPERTIES *pRequired = &(m_pPin->m_allocprops);
if (pRequest->cbAlign != pRequired->cbAlign)
{
return VFW_E_BADALIGN;
}
if (pRequest->cbPrefix != pRequired->cbPrefix)
{
return E_FAIL;
}
if (pRequest->cbBuffer > pRequired->cbBuffer)
{
return E_FAIL;
}
if (pRequest->cBuffers > pRequired->cBuffers)
{
return E_FAIL;
}
*pActual = *pRequired;
m_lCount = pRequired->cBuffers;
m_lSize = pRequired->cbBuffer;
m_lAlignment = pRequired->cbAlign;
m_lPrefix = pRequired->cbPrefix;
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -