2009-09-20 76 views
2

好吧,所以我写了一个自定义的VMR9 Allocator/Presenter,似乎工作正常。但是,当我尝试将视频帧从分配器/演示者表面复制到我的应用程序表面时,视频看起来闪烁。音频播放是好的,所以我相当肯定这不是一个机器陷入困境或任何问题。这是我在渲染循环中的代码。DirectX闪烁视频

g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 0, 0, 0), 1.0f, 0); 

// render the scene 
if (SUCCEEDED(g_pd3dDevice->BeginScene())) 
{ 
//g_pd3dDevice->SetRenderTarget(0, g_pd3dSurface); 

g_pd3dDevice->StretchRect(vmr9_ap->renderSurface, src, g_pd3dSurface, dest, D3DTEXF_NONE); 

    // end the scene 
    g_pd3dDevice->EndScene(); 
} 

但是,如果我将其更改为这个(注释掉清除缓存)

// g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 0, 0, 0), 1.0f, 0); 

// render the scene 
if (SUCCEEDED(g_pd3dDevice->BeginScene())) 
{ 
//g_pd3dDevice->SetRenderTarget(0, g_pd3dSurface); 

g_pd3dDevice->StretchRect(vmr9_ap->renderSurface, src, g_pd3dSurface, dest, D3DTEXF_NONE); 

    // end the scene 
    g_pd3dDevice->EndScene(); 
} 

这个闪烁消失。我担心这种方式很糟糕,可能会导致比解决问题更多的问题。有没有人有这方面的经验?有更好的解决方案吗?

谢谢!

回答

3

如果您打算每画面重新绘制整个视口,没有理由做清晰的事情,并且实际上可以产生很多性能提升,所以就去做吧!至于你的闪烁,这可能是不同的。你在做你正在绘制WM_PAINT消息吗?如果是这样,您可能还想拦截WM_ERASEBKGND消息,并在获取时立即返回1。这可以防止窗口试图擦除背景,并帮助我摆脱过去的一些闪烁。

仅供参考:曾经在Doom或Quake做过noclip作弊,当你走出围墙时,所有的东西都开始留下“痕迹”了吗?这是因为他们没有清除后台缓冲区,因为在正常情况下,整个场景都会重新绘制。我说如果ID足够好,对我来说就够了! :)

编辑:哦,还有更多的事情!我不确定是否需要它,但我总是在调用BeginScene()后清除AFTER。也可能导致你的闪烁。

+0

谢谢!这很有道理。如果我有声望,我会投票赞成。 – Alex 2009-09-20 06:17:12

+0

哦,并且绘图是在D3Dmage中响应WPF中的CompositionTarget.Rendering事件完成的。 – Alex 2009-09-20 06:20:36

+0

重新编辑:在BeginScene周围的每张DX卡上都不会做任何事......它不是,甚至不需要,严格来说是需要的 – Goz 2009-09-20 08:46:10

0

TBH我认为你最好编写自己的directshow渲染过滤器,将数据直接复制到纹理,然后用纹理在屏幕上绘制四边形。你会得到更好的表现。编写渲染过滤器其实很简单。特别是当你感谢你不必将它暴露给操作系统,所以大多数困难的DirectShow障碍不需要跳过。

编辑:查找“转储过滤器”,此番微软的DirectShow助手代码的一部分...

+0

你能提供一个链接吗? – Alex 2009-09-20 18:37:50

+0

不是一个链接,但所有你需要的信息已经在SDK中。 – Goz 2009-09-21 08:20:58

0

我面临着同样的问题。在我的情况下,闪烁的原因是在一个BeginScene/EndScene对内的StretchRect调用。