📄 htrencftr.cpp
字号:
CHtrEncPhysicalAllocator::Mapping* pCur = m_pMappingsList;
// Check that list exists
if( NULL == pCur )
{
HTRENC_DEBUG( "CHtrEncPhysicalAllocator::FindMapping FAILED, no mappings created yet\n" );
return NULL;
}
// Find mapping for the specified virtual address
do
{
if( pCur->pVirAddr == pVirAddr )
{
HTRENC_DEBUG_EXTRA( "CHtrEncPhysicalAllocator::FindMapping Ok\n" );
return pCur;
}
pCur = pCur->p_next;
} while( pCur != NULL );
HTRENC_DEBUG( "CHtrEncPhysicalAllocator::FindMapping FAILED, couldn't find mapping for virtual address\n" );
return NULL;
}
VOID CHtrEncPhysicalAllocator::ClearMappings()
{
// Clear the list of mapping
CHtrEncPhysicalAllocator::Mapping* pNext = NULL;
CHtrEncPhysicalAllocator::Mapping* pCur = m_pMappingsList;
do
{
if( pCur != NULL )
{
pNext = pCur->p_next;
delete pCur;
pCur = pNext;
}
} while ( pCur != NULL );
HTRENC_DEBUG_EXTRA( "CHtrEncPhysicalAllocator::ClearMappings Ok\n" );
}
HRESULT CHtrEncPhysicalAllocator::Alloc(void)
{
// Check that SetProperties has been called and there is no outstanding buffers
HRESULT hr = CBaseAllocator::Alloc();
if( FAILED(hr) )
{
HTRENC_DEBUG( "CHtrEncPhysicalAllocator::Alloc FAILED, SetProperties has not been called or there is outstanding buffers\n" );
return hr;
}
// Create CMediaSample objects and add them to the list of free objects
ALLOCATOR_PROPERTIES props;
hr = GetProperties(&props);
if( FAILED(hr) )
{
HTRENC_DEBUG( "CHtrEncPhysicalAllocator::Alloc FAILED, properties have not been set\n" );
return VFW_E_SIZENOTSET;
}
// Allocate the physical memory for each sample
for( int i = 0; i<props.cBuffers; i++ )
{
LPBYTE virAddr;
DWORD physAddr;
#ifdef UNDER_CE
virAddr = (LPBYTE)AllocPhysMem(props.cbBuffer+props.cbPrefix, PAGE_READWRITE, 0, 0, &physAddr);
#else
virAddr = (LPBYTE)malloc(props.cbBuffer+props.cbPrefix);
physAddr = (DWORD)virAddr; // simple emulation of physical address on PC environment
#endif /* UNDER_CE */
// Once the memory block is allocated, let's add the mapping to our bookkeeping
AddMapping(virAddr, physAddr);
if( NULL == virAddr )
{
HTRENC_DEBUG( "CHtrEncPhysicalAllocator::Alloc FAILED, could not allocate memory on heap\n" );
return E_OUTOFMEMORY;
}
// Create the media sample, hr is not touched by the constructor
CMediaSample* ps;
ps = new CMediaSample(NAME("Hantro Encoder Custom Sample"), this, &hr, virAddr, props.cbBuffer);
if( NULL == ps )
{
HTRENC_DEBUG( "CHtrEncPhysicalAllocator::Alloc FAILED, could not allocate memory on heap\n" );
return E_OUTOFMEMORY;
}
// Add the sample to the list of free samples and increment allocated counter
m_lFree.Add(ps);
m_lAllocated++;
}
HTRENC_DEBUG_EXTRA( "CHtrEncPhysicalAllocator::Alloc Ok\n" );
return S_OK;
}
void CHtrEncPhysicalAllocator::Free(void)
{
/* Should never be deleting this unless all buffers are freed */
ASSERT(m_lAllocated == m_lFree.GetCount());
while( m_lFree.GetCount() > 0 )
{
LPBYTE pBuf;
CMediaSample* ps = m_lFree.RemoveHead();
if( NULL != ps )
{
ps->GetPointer(&pBuf); // returns S_OK always
#ifdef UNDER_CE
FreePhysMem(pBuf); // We cannot do anything if the freeing fails
#else
free(pBuf);
#endif /* UNDER_CE */
delete ps;
m_lAllocated--;
}
else
{
break;
}
}
// Let's clear our bookkeeping of the mapping between physical and virtual addresses
ClearMappings();
HTRENC_DEBUG_EXTRA( "CHtrEncPhysicalAllocator::Free Ok\n" );
}
/*------------------------------------------------------------------------------
6. CHtrEncInputPin class
------------------------------------------------------------------------------*/
CHtrEncInputPin::CHtrEncInputPin( TCHAR* pObjectName, CTransformFilter* pTransformFilter, HRESULT* phr, LPCWSTR pName )
: CTransformInputPin( pObjectName, pTransformFilter, phr, pName ), m_pHtrAlloc(NULL)
{
}
HRESULT CHtrEncInputPin::GetAllocator(IMemAllocator **ppAllocator)
{
CheckPointer(ppAllocator, E_POINTER);
if (m_pAllocator)
{
// We already have an allocator, so return that one.
*ppAllocator = m_pAllocator;
(*ppAllocator)->AddRef();
HTRENC_DEBUG_EXTRA( "CHtrEncInputPin::GetAllocator Ok!\n" );
return S_OK;
}
// No allocator yet, so propose our custom allocator.
HRESULT hr = S_OK;
CHtrEncPhysicalAllocator *pAlloc = new CHtrEncPhysicalAllocator(&hr);
if (!pAlloc)
{
HTRENC_DEBUG( "CHtrEncInputPin::GetAllocator FAILED, out of memory\n" );
return E_OUTOFMEMORY;
}
if (FAILED(hr))
{
HTRENC_DEBUG( "CHtrEncInputPin::GetAllocator FAILED, constructing physical allocator failed\n" );
delete pAlloc;
return hr;
}
// Return the IMemAllocator interface to the caller.
HTRENC_DEBUG_EXTRA( "CHtrEncInputPin::GetAllocator Ok!\n" );
return pAlloc->QueryInterface(IID_IMemAllocator, (void**)ppAllocator);
}
HRESULT CHtrEncInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
{
IHtrAllocator* pHtrAlloc = NULL;
// Is the chosen allocator is the one we proposed, let's check out by asking for our custom interface
HRESULT hr = pAllocator->QueryInterface(IID_IHtrAllocator, (void**)&pHtrAlloc);
if( FAILED(hr) )
{
HTRENC_DEBUG( "CHtrEncInputPin::NotifyAllocator FAILED, upstream pin did not accept our allocator!\n" );
return E_FAIL;
}
m_pHtrAlloc = pHtrAlloc;
// We already have one lock for this COM object through m_pAllocator member and we use it as long
// as the base class uses. Let's leave the cleanup for the base class.
m_pHtrAlloc->Release();
HTRENC_DEBUG_EXTRA( "CHtrEncInputPin::NotifyAllocator Ok!\n" );
return S_OK;
}
/*------------------------------------------------------------------------------
7. CHtrEncOutputPin class
------------------------------------------------------------------------------*/
CHtrEncOutputPin::CHtrEncOutputPin( TCHAR* pObjectName, CTransformFilter* pTransformFilter, HRESULT* phr, LPCWSTR pName )
: CTransformOutputPin( pObjectName, pTransformFilter, phr, pName ), m_pHtrAlloc(NULL)
{
}
STDMETHODIMP CHtrEncOutputPin::NonDelegatingQueryInterface(REFIID iid, void **ppv)
{
if (iid == IID_IAMStreamConfig ) {
return GetInterface(static_cast<IAMStreamConfig*>(this), ppv);
}
else if( iid == IID_IAMVideoCompression ) {
return GetInterface(static_cast<IAMVideoCompression*>(this), ppv);
}
return CTransformOutputPin::NonDelegatingQueryInterface(iid,ppv);
}
HRESULT CHtrEncOutputPin::DecideAllocator(IMemInputPin *pPin, IMemAllocator **pAlloc)
{
CheckPointer(pAlloc, E_POINTER);
// Let's forget about the downstream pins requirements, we need our on allocator, period.
HRESULT hr;
ALLOCATOR_PROPERTIES ownProps;
IMemAllocator* pOwnAlloc = new CHtrEncPhysicalAllocator(&hr);
if( NULL == pOwnAlloc )
{
HTRENC_DEBUG( "CHtrEncInputPin::DecideAllocator FAILED, not enough memory for allocator!\n" );
return E_OUTOFMEMORY;
}
// Query our custom interface from the allocator
IHtrAllocator* pHtrAlloc;
hr = pOwnAlloc->QueryInterface(IID_IHtrAllocator, (void**)&pHtrAlloc);
if( FAILED(hr) )
{
HTRENC_DEBUG( "CHtrEncInputPin::DecideAllocator FAILED, upstream pin did not accept our allocator!\n" );
return E_FAIL;
}
m_pHtrAlloc = pHtrAlloc;
// Call DecideBufferSize to set the properties for our allocator
hr = DecideBufferSize(pOwnAlloc, &ownProps);
if( FAILED(hr) )
{
// If we cannot decide the allocator properties for some reason, cascade the error
HTRENC_DEBUG( "CHtrEncOutputPin::DecideAllocator FAILED, failed to decide the allocator properties\n" );
return hr;
}
// Call IMemInputPin::NotifyAllocator to tell the downstream pin that we are using our own allocator.
hr = pPin->NotifyAllocator(pOwnAlloc, TRUE);
if( FAILED(hr) )
{
// If the downstream pin cannot live with our requirements, let's forget it and cascade the error
HTRENC_DEBUG( "CHtrEncOutputPin::DecideAllocator FAILED, downstream pin rejected our allocator\n" );
return hr;
}
// Set the pointer to the allocator correctly
*pAlloc = pOwnAlloc;
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::DecideAllocator Ok!\n" );
return S_OK;
}
// Methods from IAMStreamConfig
HRESULT CHtrEncOutputPin::GetFormat(AM_MEDIA_TYPE** ppmt)
{
if( !m_pFilter->GetPin(0)->IsConnected() )
{
HTRENC_DEBUG( "CHtrEncOutputPin::GetFormat FAILED, input pin must be connected\n" );
return VFW_E_NOT_CONNECTED;
}
CMediaType mt;
HRESULT hr = ((CHtrEncFltr*)m_pFilter)->GetMediaType( 0, &mt );
if( FAILED(hr) )
{
HTRENC_DEBUG( "CHtrEncOutputPin::GetFormat: filter->GetMediaType FAILED\n" );
return hr;
}
*ppmt = CreateMediaType( &mt );
if( *ppmt == NULL )
{
HTRENC_DEBUG( "CHtrEncOutputPin::GetFormat FAILED creating media type\n" );
return E_OUTOFMEMORY;
}
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::GetFormat Ok!\n" );
return S_OK;
}
HRESULT CHtrEncOutputPin::SetFormat(AM_MEDIA_TYPE* pmt)
{
if( !m_pFilter->GetPin(0)->IsConnected()) return VFW_E_NOT_CONNECTED;
CMediaType mt( *pmt );
// Check new format using CTransformOutputPin, which calls our
// implementation in CHtrEncFltr
HRESULT hr = CheckMediaType( &mt );
if( FAILED(hr) )
{
HTRENC_DEBUG( "CHtrEncOutputPin::SetFormat: CheckMediaType FAILED, invalid format?\n" );
return hr;
}
// Set new format, also using CTransformOutputPin
hr = SetMediaType( &mt );
if( FAILED(hr) )
{
HTRENC_DEBUG( "CHtrEncOutputPin::SetFormat: SetMediaType FAILED, invalid format?\n" );
return hr;
}
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::SetFormat Ok!\n" );
return S_OK;
}
HRESULT CHtrEncOutputPin::GetNumberOfCapabilities(int* piCount, int* piSize)
{
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::GetNumberOfCapabilities WARNING: not implemented!\n" );
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::GetStreamCaps(int iIndex, AM_MEDIA_TYPE** pmt, BYTE* pSCC)
{
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::GetStreamCaps WARNING: not implemented!\n" );
return E_NOTIMPL;
}
// Methods from IAMVideoCompression
HRESULT CHtrEncOutputPin::put_KeyFrameRate(long KeyFrameRate)
{
if( !m_pFilter->GetPin(0)->IsConnected()) return VFW_E_NOT_CONNECTED;
// Set intra refresh directly in CHtrEncFltr
CHtrEncFltr* pHtrEncFltr = (CHtrEncFltr*)m_pFilter;
if( pHtrEncFltr==NULL )
{
HTRENC_DEBUG( "CHtrEncOutputPin::put_KeyFrameRate: not connected to CHtrEncFltr object\n" );
return E_FAIL;
}
if( KeyFrameRate < 0 )
{
HTRENC_DEBUG( "CHtrEncOutputPin::put_KeyFrameRate FAILED, invalid KeyFrameRate input\n" );
return VFW_E_TYPE_NOT_ACCEPTED;
}
pHtrEncFltr->m_settings.intraRefreshRate = KeyFrameRate;
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::put_KeyFrameRate Ok!\n" );
return S_OK;
}
HRESULT CHtrEncOutputPin::get_KeyFrameRate(long *pKeyFrameRate)
{
if( !m_pFilter->GetPin(0)->IsConnected()) return VFW_E_NOT_CONNECTED;
if( pKeyFrameRate==NULL )
{
HTRENC_DEBUG( "CHtrEncOutputPin::get_KeyFrameRate FAILED, null pKeyFrameRate input\n" );
return E_INVALIDARG;
}
// Get intra refresh directly from CHtrEncFltr
CHtrEncFltr* pHtrEncFltr = (CHtrEncFltr*)m_pFilter;
if( pHtrEncFltr==NULL )
{
HTRENC_DEBUG( "CHtrEncOutputPin::get_KeyFrameRate: not connected to CHtrEncFltr object\n" );
return E_FAIL;
}
*pKeyFrameRate = pHtrEncFltr->m_settings.intraRefreshRate;
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::get_KeyFrameRate Ok!\n" );
return S_OK;
}
HRESULT CHtrEncOutputPin::GetInfo( WCHAR* pszVersion, int* pcbVersion,
LPWSTR pszDescription, int* pcbDescription,
long* pDefaultKeyFrameRate, long* /*pDefaultPFramesPerKey*/,
double* /*pDefaultQuality*/, long* pCapabilities )
{
(void)pszVersion; (void)pcbVersion;
(void)pszDescription; (void)pcbDescription;
// Zero means only first frame is key frame
if( pDefaultKeyFrameRate != NULL )
*pDefaultKeyFrameRate = 0;
// Only key frame rate is supported
if( pCapabilities != NULL )
*pCapabilities = CompressionCaps_CanKeyFrame;
HTRENC_DEBUG_EXTRA( "CHtrEncOutputPin::GetInfo Ok!\n" );
return S_OK;
}
HRESULT CHtrEncOutputPin::put_PFramesPerKeyFrame(long PFramesPerKeyFrame)
{
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::get_PFramesPerKeyFrame(long *pPFramesPerKeyFrame)
{
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::put_Quality(double Quality)
{
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::get_Quality(double *pQuality)
{
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::put_WindowSize(DWORDLONG WindowSize)
{
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::get_WindowSize(DWORDLONG *pWindowSize)
{
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::OverrideKeyFrame(long FrameNumber)
{
return E_NOTIMPL;
}
HRESULT CHtrEncOutputPin::OverrideFrameSize(long FrameNumber, long Size)
{
return E_NOTIMPL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -