⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 samplegrabber.cpp

📁 Window Mobile Capture with DirectDraw
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	// 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 + -