DirectShow Ball filter 的FillBuffer函数问题

huabinsir 2009-12-29 04:35:00
由于可用分有限,已在流媒体论坛发了贴。所以本贴分数不高,请高人别介意.


DirectShow Ball filter 的范例 (D:\DXSDK\Samples\C++\DirectShow\Filters\Ball)

FillBuffer函数 是对 Sample数据的填充。例1 中可见到小球在跳动.
例2的想法是对Sample填充一种颜色. [RGB(128, 128, 128)或RGB(0x80, 0x80, 0x80) , 不是黑色],
但例2的效果是黑屏,不知什么原因?是填充FillBuffer函数写得不对?

例1:
HRESULT CBallStream::FillBuffer(IMediaSample *pms)
{
BYTE *pData;
long lDataLen;

pms->GetPointer(&pData);
lDataLen = pms->GetSize();

// If true then we clear the output buffer and don't attempt to
// erase a previous drawing of the ball - this will be the case
// when we start running as the buffer will be full of rubbish
if( m_bZeroMemory ) {
ZeroMemory( pData, lDataLen );
}

{
CAutoLock cAutoLockShared(&m_cSharedState);

// If we haven't just cleared the buffer delete the old
// ball and move the ball on

if( !m_bZeroMemory ){
BYTE aZeroes[ 4 ] = { 0, 0, 0, 0 };
m_Ball->PlotBall(pData, lDataLen, aZeroes, m_iPixelSize);
m_Ball->MoveBall(m_rtSampleTime - (LONG) m_iRepeatTime);
}

m_Ball->PlotBall(pData, lDataLen, m_BallPixel, m_iPixelSize);

// The current time is the sample's start
CRefTime rtStart = m_rtSampleTime;

// Increment to find the finish time
m_rtSampleTime += (LONG)m_iRepeatTime;

pms->SetTime((REFERENCE_TIME *) &rtStart,(REFERENCE_TIME *) &m_rtSampleTime);
}

m_bZeroMemory = FALSE;
pms->SetSyncPoint(TRUE);

return NOERROR;

} // FillBuffer


例2:
HRESULT CBallStream::FillBuffer(IMediaSample *pms)
{
BYTE *pData;
long lDataLen;

pms->GetPointer(&pData);
lDataLen = pms->GetSize();

// If true then we clear the output buffer and don't attempt to
// erase a previous drawing of the ball - this will be the case
// when we start running as the buffer will be full of rubbish
if( m_bZeroMemory ) {
ZeroMemory( pData, lDataLen );
}


#if 1
BYTE *pTmpData;
pTmpData = new BYTE[230400]; //320*240*3 = 230400
memset(pTmpData, 0x80, 230400); //128
//FillMemory(buf, sizeof(buf), 0);
pData = pTmpData;
lDataLen = 230400;

// The current time is the sample's start
CRefTime rtStart = m_rtSampleTime;
// Increment to find the finish time
m_rtSampleTime += (LONG)m_iRepeatTime;
pms->SetTime((REFERENCE_TIME *) &rtStart,(REFERENCE_TIME *) &m_rtSampleTime);

#endif


m_bZeroMemory = FALSE;
pms->SetSyncPoint(TRUE);


#if 1
delete [] pTmpData;
pTmpData = NULL;
#endif

return NOERROR;

} // FillBuffer
...全文
232 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
神-气 2012-09-11
  • 打赏
  • 举报
回复

lDataLen = 230400; //你这完全是强暴,把人家的内存大小进行修改,但是人家的实际内存大小并没有任何改变


哈哈
yinfuyong 2009-12-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 huabinsir 的回复:]
Filter(Source Filter)如何读取 外部buffer 中的数据?


要播放buffer里的数据(从网络中收到的一包一包的),

自已写了一个Filter(Source Filter), 注册进了操作系统.

自已写的Filter中如何取buffer中的数据呢?


应用软件(CMedia包装类)按如下方式调用该Filter:

hr = CoCreateInstance( CLSID_BouncingBall, NULL,
                  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &pBall);
hr = pGB->AddFilter(pBall, L"Bouncing Ball");

[/Quote]
=======================================================================
一般是在Transform函数里面
huabinsir 2009-12-30
  • 打赏
  • 举报
回复
Filter(Source Filter)如何读取 外部buffer 中的数据?


要播放buffer里的数据(从网络中收到的一包一包的),

自已写了一个Filter(Source Filter), 注册进了操作系统.

自已写的Filter中如何取buffer中的数据呢?


应用软件(CMedia包装类)按如下方式调用该Filter:

hr = CoCreateInstance( CLSID_BouncingBall, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &pBall);
hr = pGB->AddFilter(pBall, L"Bouncing Ball");
linkboycn 2009-12-30
  • 打赏
  • 举报
回复
BYTE *pTmpData;
pTmpData = new BYTE[230400]; //320*240*3 = 230400
memset(pTmpData, 0x80, 230400); //128
//FillMemory(buf, sizeof(buf), 0);
pData = pTmpData;
lDataLen = 230400;
may be have no use. the memset you really wanna to is like below:
memset(pData, 0x80, lDataLen);

there is no need to alloc a new buffer, just to manipulate the buffer in the mediasample.
jtujtujtu 2009-12-30
  • 打赏
  • 举报
回复
sharimg mem
其他方式暂不了解
呵呵
huabinsir 2009-12-30
  • 打赏
  • 举报
回复
我的意思是:

原来ball(Filter)的数据buffer是自己生成的。

FillBuffer函数是Filter的函数。已经注册到系统了,不能改变了.
HRESULT CBallStream::FillBuffer(IMediaSample *pms)
{
BYTE *pData;
long lDataLen;

pms->GetPointer(&pData);
lDataLen = pms->GetSize();

FillMemory(pData,0x80,lDataLen);//就这一句就可以
...........

pms->SetSyncPoint(TRUE);
return NOERROR;
} // FillBuffer


Filter已经注册进了系统。外部的程序调用Filter. 外部的程序获得的数据buffer, 如何给Filter?

是要另外写接口还是有其它什么方法?
昨夜无风 2009-12-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 huabinsir 的回复:]
Filter(Source Filter)如何读取 外部buffer 中的数据?


要播放buffer里的数据(从网络中收到的一包一包的),

自已写了一个Filter(Source Filter), 注册进了操作系统.

自已写的Filter中如何取buffer中的数据呢?


应用软件(CMedia包装类)按如下方式调用该Filter:

hr = CoCreateInstance( CLSID_BouncingBall, NULL,
                  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **) &pBall);
hr = pGB->AddFilter(pBall, L"Bouncing Ball");

[/Quote]

要看你的buffer数据是怎么来的,假如是自己生成的,比如原ball的数据就是自己生成的。你可以直接对pData进行操作,当然要注意内存大小。假如是自己读出来的数据(比如从文件读的),那你就要把读出来的一帧数据(lDataLen )拷贝给pData就可以了。
昨夜无风 2009-12-30
  • 打赏
  • 举报
回复
例2:

HRESULT CBallStream::FillBuffer(IMediaSample *pms)
{
BYTE *pData;
long lDataLen;
pms->GetPointer(&pData);
lDataLen = pms->GetSize();

if( m_bZeroMemory ) {
ZeroMemory( pData, lDataLen ); //已经对Sample的内存清为黑色
}

#if 1
BYTE *pTmpData;
pTmpData = new BYTE[230400]; //你这是自己分配的内存,而不是sample的,sample有自己的内存指针,pData
memset(pTmpData, 0x80, 230400); //把你自己的内存填充
pData = pTmpData; //把sample的内存指针指向你自己的内存,但是sample的内存并没有更改和释放,里面还是全是零
lDataLen = 230400; //你这完全是强暴,把人家的内存大小进行修改,但是人家的实际内存大小并没有任何改变

........
#endif

#if 1
delete [] pTmpData; //把你的内存释放,但是sample真正的内存并没任何改变
pTmpData = NULL;
#endif

return NOERROR;

} // FillBuffer


以上是对你的问题进行的简单描述,其实最根本的原因是你没有认清楚sample的内存。sample是在整个期间都要用到的,假如按你的意思,你填充了就释放,那后面的filter接收到得就是内存释放掉的sample,肯定会出问题。

其实,要实现你的程序,很简单,根本不需要自己分配内存。

HRESULT CBallStream::FillBuffer(IMediaSample *pms)
{
BYTE *pData;
long lDataLen;

pms->GetPointer(&pData);
lDataLen = pms->GetSize();

// If true then we clear the output buffer and don't attempt to
// erase a previous drawing of the ball - this will be the case
// when we start running as the buffer will be full of rubbish
if( m_bZeroMemory ) {
ZeroMemory( pData, lDataLen );
}


#if 1
FillMemory(pData,0x80,lDataLen);//就这一句就可以

// The current time is the sample's start
CRefTime rtStart = m_rtSampleTime;
// Increment to find the finish time
m_rtSampleTime += (LONG)m_iRepeatTime;
pms->SetTime((REFERENCE_TIME *) &rtStart,(REFERENCE_TIME *) &m_rtSampleTime);
#endif

m_bZeroMemory = FALSE;

pms->SetSyncPoint(TRUE);
return NOERROR;
} // FillBuffer
huabinsir 2009-12-29
  • 打赏
  • 举报
回复
UP

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧