大家好,
我有一个变换过滤器,它接受两个输入,一个来自相机,另一个来自文件源。在我的变换过滤器中,我混合了来自两个来源的输入。
变换过滤器派生自 CTransformFilter
class CWMTransformFilter : public CTransformFilter
并且额外的引脚来自:CTransformInputPin(它又来自 CBaseInputPin)
class CFileInputPin : public CTransformInputPin
就我而言,正在发生的事情是,如果文件源很小(假设 10 秒),我也会从相机获得输入 10 秒,稍后相机会停止向输入引脚发送帧。
所以我现在需要的是:
1. 即使源过滤器停止发送,如何通知相机发送帧?
2. 源文件播放停止时如何重启源过滤器? (类似于循环播放文件)
更新:
STDMETHODIMP CFileInputPin::EndOfStream()
{
//return CTransformInputPin::EndOfStream();
return S_OK;
}
STDMETHODIMP CFileInputPin::Receive(IMediaSample* pSample)
{
HRESULT hr;
BYTE* pBufferIn;
long lBufferLength, lBufferSize;
hr = CBaseInputPin::Receive(pSample);
if (FAILED(hr))
{
printf("Error !!\n");
return hr;
}
hr = pSample->GetPointer(&pBufferIn);
DWORD stat = WaitForSingleObject(m_pFil->m_QSem,0L);
BOOL bSem = FALSE;
if( WAIT_OBJECT_0 == stat )
{
BYTE *pBuf = (BYTE *) malloc( Wsize*2 );
memcpy(pBuf,pBufferIn,Wsize); //lBufferLength);
sEncodedFrame CurFrame={pBuf,Wsize};
m_pFil->m_Q.push(CurFrame); //push it onto the queue
bSem = ReleaseSemaphore(m_pFil->m_QSem,1,NULL);
if(!bSem)
{
printf("ReleaseSemaphore error: %d \n", GetLastError());
}
return S_OK;
}
else
{
printf("Cant Receive frame 0x%x \n",stat);
return E_FAIL;
}
return S_OK;
}
HRESULT CWMTransformFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
unsigned char r,g,b;
unsigned char y,u,v;
BYTE *pBufferIn, *pBufferOut, *pBuf;
HRESULT hr = pSource->GetPointer(&pBufferIn);
hr = pDest->GetPointer(&pBufferOut);
if (FAILED(hr))
{
return hr;
}
long srclen = pSource->GetActualDataLength();
long dstlen = pDest->GetActualDataLength();
LONG pLastCnt;
BOOL bSem = FALSE;
//printf("Waiting to fill buffer %d\n",pSource);
//return S_OK;
//try
//{
while(1)
{
//if(1)
DWORD ret = WaitForSingleObject(m_QSem,0L);
if(ret != WAIT_OBJECT_0)
{
printf("Get error %d \n",GetLastError());
}
if( WAIT_OBJECT_0 == ret )
{
sEncodedFrame Frame;
if( m_Q.empty() == false )
{
Frame = m_Q.front();
m_Q.pop();
pBuf = (BYTE*) malloc(dstlen*2);
pLastCnt = Frame.iValidSize;
printf("Copy onto queue \n");
memcpy(pBuf,Frame.pFrame,pLastCnt); //Frame.iValidSize);
free(Frame.pFrame);
//delete &Frame;
bSem = ReleaseSemaphore(m_QSem,1,NULL);
if(!bSem)
{
printf("ReleaseSemaphore error: %d \n", GetLastError());
}
hr = S_OK;
break;
}
else
{
bSem = ReleaseSemaphore(m_QSem,1,NULL);
if(!bSem)
{
printf("ReleaseSemaphore error: %d \n", GetLastError());
}
//return S_OK;
hr = E_FAIL;
}
}
else
{
//return S_OK;
hr = E_FAIL;
}
}
for(i = 0; i < windowWidth*2*windowHeight ; i+=4)
{
y = pBufferIn[i];
u = pBufferIn[i+1];
v = pBufferIn[i+3];
r = y + 1.4075 * (v - 128);
g = y - 0.3455 * (u - 128) - (0.7169 * (v - 128));
b = y + 1.7790 * (u - 128);
if(((r > b) &&(g > b)) && (g <= 200) )
{
pBufferIn[i] = pBuf[i];
pBufferIn[i+1] = pBuf[i+1];
pBufferIn[i+2] = pBuf[i+2];
pBufferIn[i+3] = pBuf[i+3];
}
}
// Process the data.
memcpy(pBufferOut,pBufferIn,pSource->GetSize()); //after blend
pDest->SetActualDataLength(pDest->GetSize());
pDest->SetSyncPoint(TRUE);
return S_OK;
}
CFileInputPin::Receive 是我从文件输入引脚
CFileInputPin::EndOfStream() 接收样本的地方,通知样本已完成。
CWMTransformFilter::Transform(),是将样本发送到渲染器的输出端的位置。
谢谢,
希亚姆