views:

360

answers:

2

Alright, so I wrote a custom VMR9 Allocator/Presenter which seems to work fine. However, when I attempt to copy video frames from the Allocator/Presenter surfaces into my application surfaces, the video appears to flicker. Audio playback is fine so I'm fairly certain it's not an issue of the machine being bogged down or anything. This is the code I have in my render loop.

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();
}

However, if I change it to this (commenting out clearing the buffer)

// 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();
}

this flickering goes away. I'm worried that this is somehow bad form/hackish and might cause more problems than it solves. Does anyone have any experience in this area? Is there a better solution?

Thanks!

+2  A: 

If you intend to repaint the entire viewport every frame there is no reason to do a clear, and it can actually yield a lot of performance gains, so go for it! As for your flickering, that might be something different. Are you doing you're drawing in a WM_PAINT message? If so, you may want to also intercept the WM_ERASEBKGND message and simply return 1 when you get it. This prevents windows from trying to erase the background and has helped me get rid of some flickering in the past.

FYI: Ever do the noclip cheat in Doom or Quake, and when you walk outside a wall everything starts leaving "trails" all over? That's because they're not clearing the back buffer, since under normal circumstances the entire scene would be redrawn every time anyway. I say if it's good enough for id it's good enough for me! :)

Edit: Oh, and on more thing! I'm not sure if it's required or not, but I always do my clear AFTER calling BeginScene(). Could also be contributing to your flicker.

Toji
Thanks! That makes a lot of sense. I'd vote this up, if I had the reputation.
Alex
Oh, and the drawing is done in response to a CompositionTarget.Rendering event in WPF, inside a D3DImage.
Alex
re your edit: On every DX card around BeginScene does nothing .... its not even, strictly, needed
Goz
Technically yes, but in the strictest sense it's up to the driver manufacturer to determine what it does and therefore is best to use it "correctly".
Toji
Actually no ... the fact that Begin/EndScene could be bypassed caused a real problem for PowerVR initially. In the end even THEY moved over to just capturing all calls between presents. This is why it has been removed in DirectX10. Half the problem comes from the fact that Microsoft never really specified what was supposed to go between Begin/EndScene pairs.
Goz
A: 

TBH i reckon you are best off writing your own directshow render filter that copies the data directly to a texture and then drawing a quad over the screen with the texture. You'd get much better performance. Writing a render filter is actually pretty easy. Especially when you appreciate you don't have to expose it to the operating system so most of the difficult DirectShow hurdles don't need t be jumped.

Edit: Look up the "Dump Filter" it comes as part of Microsoft's DirectShow helper code ...

Goz
Can you provide a link?
Alex
Not a link but all the info you need is already in the SDK.
Goz