📄 dxfilter.cpp
字号:
if( m_callback ) { REFERENCE_TIME StartTime, StopTime; pms->GetTime( &StartTime, &StopTime); StartTime += m_pInput->CurrentStartTime( ); StopTime += m_pInput->CurrentStartTime( ); BOOL * pTypeChanged = &((CDXFilterInPin*) m_pInput)->m_bMediaTypeChanged; HRESULT hr = m_callback( pms, &StartTime, &StopTime, *pTypeChanged ); *pTypeChanged = FALSE; // now that we notified user, we can clear it return hr; } return NOERROR;}//----------------------------------------------------------------------------// SetAcceptedMediaType//----------------------------------------------------------------------------STDMETHODIMP CDXFilter::SetAcceptedMediaType( const CMediaType * pmt ){ CAutoLock lock( &m_Lock ); if( !pmt ) { m_mtAccept = CMediaType( ); return NOERROR; } HRESULT hr;#if !defined(_WIN32_WCE) hr = CopyMediaType( &m_mtAccept, pmt );#else hr=S_OK; CopyMediaType( &m_mtAccept, pmt );#endif return hr;}//----------------------------------------------------------------------------// GetAcceptedMediaType//----------------------------------------------------------------------------STDMETHODIMP CDXFilter::GetConnectedMediaType( CMediaType * pmt ){ if( !m_pInput || !m_pInput->IsConnected( ) ) { return VFW_E_NOT_CONNECTED; } return m_pInput->ConnectionMediaType( pmt );}//----------------------------------------------------------------------------// SetCallback//----------------------------------------------------------------------------STDMETHODIMP CDXFilter::SetCallback( SAMPLECALLBACK Callback ){ CAutoLock lock( &m_Lock ); m_callback = Callback; return NOERROR;}//----------------------------------------------------------------------------// inform the input pin of the allocator buffer we wish to use. See the// input pin's SetDeliverBuffer method for comments. //----------------------------------------------------------------------------STDMETHODIMP CDXFilter::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 ((CDXFilterInPin*)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 CDXFilterInPin::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( ((CDXFilter*)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 CDXFilterInPin::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( !((CDXFilter*)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 ((CDXFilter*)m_pTIPFilter)->OutputPin( )->GetConnected()->EnumMediaTypes( ppEnum );}//----------------------------------------------------------------------------////----------------------------------------------------------------------------STDMETHODIMP CDXFilterInPin::NotifyAllocator( IMemAllocator *pAllocator, BOOL bReadOnly ){ if( m_pPrivateAllocator ) { if( pAllocator != m_pPrivateAllocator ) { return E_FAIL; } else {#if !defined(_WIN32_WCE) // 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 && !DXFilter( )->IsReadOnly( ) ) { return E_FAIL; }#endif } } return CTransInPlaceInputPin::NotifyAllocator( pAllocator, bReadOnly );}//----------------------------------------------------------------------------////----------------------------------------------------------------------------STDMETHODIMP CDXFilterInPin::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 CDXFilterInPin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES *pProps ){ CheckPointer(pProps,E_POINTER); if (m_pPrivateAllocator) { *pProps = m_allocprops; return S_OK; } else { return CTransInPlaceInputPin::GetAllocatorRequirements(pProps); }}//----------------------------------------------------------------------------////----------------------------------------------------------------------------HRESULT CDXFilterInPin::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 CDXFilterAllocator( this, &hr ); if( !m_pPrivateAllocator ) { return E_OUTOFMEMORY; } m_pPrivateAllocator->AddRef( ); return hr;}//----------------------------------------------------------------------------////----------------------------------------------------------------------------HRESULT CDXFilterInPin::SetMediaType( const CMediaType *pmt ){ m_bMediaTypeChanged = TRUE; return CTransInPlaceInputPin::SetMediaType( pmt );}//----------------------------------------------------------------------------// don't allocate the memory, just use the buffer the app provided//----------------------------------------------------------------------------HRESULT CDXFilterAllocator::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 CDXFilterAllocator::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 CDXFilterAllocator::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 + -