Sample虽然也是一个COM组件,但它的生命周期与普通的COM组件有些不一样。
(1)在实际应用中,Sample由Pin上的Sample管理器创建,并维持在一个空闲
Sample队列中。当Filter要使用一个Sample时,会调用IMemAllocator::GetBuffer
从上述队列中取出一个空Sample,此时这个Sample的引用计数会增加1;
(2)当Filter使用完这个Sample后,调用Sample对象的Release函数。如果这个Sample上
的引用计数变成0,它不会像一般的COM组件一样析构自己,而是调用Sample管理器的
IMemAllocator::ReleaseBuffer函数,把自己重新加入到空闲Sample队列中,代码如下:
//Sample对象上的Release函数实现
STDMETHODIMP _(ULONG) CMediaSample::Release()
{
//Decrement our own private reference count
LONG lRef;
if(m_cRef==1)
{
lRef=0;
m_cRef=0;
}
else
{
lRef=InterlockedDecrement(&m_cRef);
}
ASSERT(lRef>=0);
DbgLog((LOG_MEMORY,3,TEXT(" Unknown %X ref-- = %d"),this,m_cRef));
//Did we release our final reference count
if(lRef==0)
{
//Free all resources
if(m_dwFlags&Sample_TypeChanged)
{
SetMediaType(NULL);
}
ASSERT(m_pMediaType==NULL);
m_dwFlags=0;
m_dwTypeSpecificFlags=0;
m_dwStreamId=AM_STREAM_MEDIA;
//This may cause us to be deleted
//Our refcount is reliably 0 thus no-one will mess with us
m_pAllocator->ReleaseBuffer(this);
}
return (ULONG)lRef;
}
(1)在实际应用中,Sample由Pin上的Sample管理器创建,并维持在一个空闲
Sample队列中。当Filter要使用一个Sample时,会调用IMemAllocator::GetBuffer
从上述队列中取出一个空Sample,此时这个Sample的引用计数会增加1;
(2)当Filter使用完这个Sample后,调用Sample对象的Release函数。如果这个Sample上
的引用计数变成0,它不会像一般的COM组件一样析构自己,而是调用Sample管理器的
IMemAllocator::ReleaseBuffer函数,把自己重新加入到空闲Sample队列中,代码如下:
//Sample对象上的Release函数实现
STDMETHODIMP _(ULONG) CMediaSample::Release()
{
//Decrement our own private reference count
LONG lRef;
if(m_cRef==1)
{
lRef=0;
m_cRef=0;
}
else
{
lRef=InterlockedDecrement(&m_cRef);
}
ASSERT(lRef>=0);
DbgLog((LOG_MEMORY,3,TEXT(" Unknown %X ref-- = %d"),this,m_cRef));
//Did we release our final reference count
if(lRef==0)
{
//Free all resources
if(m_dwFlags&Sample_TypeChanged)
{
SetMediaType(NULL);
}
ASSERT(m_pMediaType==NULL);
m_dwFlags=0;
m_dwTypeSpecificFlags=0;
m_dwStreamId=AM_STREAM_MEDIA;
//This may cause us to be deleted
//Our refcount is reliably 0 thus no-one will mess with us
m_pAllocator->ReleaseBuffer(this);
}
return (ULONG)lRef;
}
(3)直到Sample管理器调用IMemAllocator::Decommit时,Sample对象才真正被析构掉。