Capturing multiple windows from a single game process with DXIFRShim

Hi,

Question:
I have a game that launches 2 or more windows when the game starts. Is there a way to read the frames from both these windows simultaneously with separate outputs?

What’s happening:
What I have happening is that both windows are having their frames captured, and the output video is displaying frames that switch between the 2 windows quickly.

What I’ve done:
I’ve modified the shim program so that it does not need StartApp.exe to obtain parameters from. It now starts with the parameters hardcoded into NvIFREncoder.cpp.

I was hoping that each window would start with their own instance of the shim layer, but it does not seem to be the case.

I’ve also tried changing the number of buffers (params.dwNBuffers), but index 0 of that buffer still captures the frames from both windows.

Question again:
So, how exactly do I have each window output into their own video, instead of both writing into the same video (which is what is happening now)?

Hi,

The shim only creates one NvIFREncoder, so there’s only one H264 stream generated. If you want to capture two DX windows, you need two instances of NvIFREncoder.

Gary

Hmm, this is done in IDXGISwapChain.cpp, correct?

In particular,

static NvIFREncoder *pEncoder;
pEncoder = new NvIFREncoderDXGI<ID3D11Device, ID3D11Texture2D>(This, desc.Width, desc.Height, 
                                                               desc.Format, FALSE, pAppParam);
pEncoder->StartEncoder();

The current behavior seems to be capturing from both windows and passing their frames into this single NvIFREncoder. Does this mean that I have to create an additional swap chain as well? Then pass the respective swap chain/buffer into the encoder? As done in the following:

NvIFREncoderDXGI<ID3D10Device, ID3D10Texture2D> *)pEncoder)->UpdateSharedSurface(pD3D10Device, <i><b>pBackBuffer</b></i>)

I’m very new at DirectX programming, apologies if I asking strange or obvious stuff.

Please check if the

IDXGISwapChain * This

argument has different values for the different windows. If yes, create one NvIFREncoderDXGI for each of them.

They are indeed different.

I went ahead to create one NvIFREncoderDXGI for each of them like you said. I now have the following variables:

NvIFREncoder *pEncoder0;
NvIFREncoder *pEncoder1;
IDXGISwapChain *Window0;
IDXGISwapChain *Window1;

Individually, they work fine. What I mean is that when I launch both windows, I comment out Window1/pEncoder1 and I can capture from Window0 and output to pEncoder0 without issues. I then comment out Window0/pEncoder0 and uncomment Window1/pEncoder1. That works great too. The input capture and output streams all work perfectly.

But when I have both enabled, both pEncoder0 and pEncoder1 are getting their input from Window1 (Window1 launches after Window0). They both output into their own stream as intended though. This is very strange. I’m quite sure I’m not having a brain fart here in my code.

There’s this line in the DXGI.shim.log that says “Only one adapter found. Using it without further checks.” Is this the reason why I’m getting the problem I have? I’ve also noticed that the “pEncoder->StartEncoder()” threading isn’t actually being threaded as well (pEncoder0 doesn’t actually start until after pEncoder1 has started)

Found the bug. NvIFREncoder needs an additional buffer variable as well. The buffer was being overwritten by Window1’s data.

However this still remains true. I’ll update if I manage to find out why.

Edit: I’ve found out why. The NvIFREncoder needs additional gpuEvent handles as well (for ppTransferCompletionEvents)