Advertisement

[DirectX11]How to capture the rendered scene D3D11?

Started by September 01, 2017 09:54 AM
14 comments, last by SoldierOfLight 7 years, 5 months ago

I am writing code for capturing Skype video call for windows 10, I am facing an issue as following:

1). Skype use Directx11, and I am able to hook into the IDXGISwapChain::Present, and use code as below to capture the screenshot:


ID3D11Device *device = NULL;
	HRESULT hr = pswap->GetDevice(__uuidof(ID3D11Device), (void**)&device);
	if (hr != S_OK)
	{
		OutputDebugStringA("++++++++ GetDevice failed ++++++");
		return;
	}
	ID3D11DeviceContext *context;
	device->GetImmediateContext(&context);

	ID3D11Texture2D* backBuffer = nullptr;
	hr = pswap->GetBuffer(0, __uuidof(*backBuffer), (LPVOID*)&backBuffer);
	if (hr != S_OK)
	{
		OutputDebugStringA("++++++++ IDXGISwapChain::GetBuffer failed++++++");
		return;
	}

	//Save to a JPG file
    hr = SaveWICTextureToFile(context, backBuffer,
			GUID_ContainerFormatJpeg, strScreenPath);


	SafeRelease(device);
	SafeRelease(context);
	SafeRelease(backBuffer);

The problem is what I captured is either the local video frame(camera) or the remote video frame, what I want to capture is synthetic image, just like I see on the Skype window during a video call, I remember that in D3D9, there is a GetRenderTargetData() to retrieve the raw data from the back buffer, and it contains the rendered scene which is the same as I see on the Skype window during the video call, but I can't find a way to do this in D3D11....

Any advise is appreciated.

 

HI!

Doesn't Skype have like a floating window to show the remote camera? Maybe they are rendering to two different windows and you should have to do some compositing.

Advertisement

Hi piluve, 

Thanks for your reply, I checked the OutputWindow in the DXGI_SWAP_CHAIN_DESC, the value is NULL.

And there is only one swap chain instance as well.



 

You could also try to use the ID3D11DeviceContext::OMGetRenderTargets() and then get the resource from the returned view.

Yes, actually I tried this as well, see the code below:


	ID3D11Texture2D* pbackBuffer = nullptr;
	hr = pswap->GetBuffer(0, __uuidof(*pbackBuffer), (LPVOID*)&pbackBuffer);
	if (hr != S_OK)
	{
		OutputDebugStringA("++++++++ IDXGISwapChain::GetBuffer failed++++++");
		SafeRelease(device);
		SafeRelease(pcontext);
		return hr;
	}

	ID3D11RenderTargetView *pRenderTargetView = NULL;
	// use the back buffer address to create the render target
	hr = device->CreateRenderTargetView(pbackBuffer, NULL, &pRenderTargetView);
	if (hr != S_OK)
	{
		OutputDebugStringA("++++++++ IDXGISwapChain::CreateRenderTargetView failed++++++");
		SafeRelease(device);
		SafeRelease(pcontext);
		return hr;
	}

	pcontext->OMSetRenderTargets(1, &pRenderTargetView, NULL);

	ID3D11Resource* pRenderTRes = NULL;
	pRenderTargetView->GetResource(&pRenderTRes);

    hr = SaveWICTextureToFile(pcontext, pRenderTRes,
			GUID_ContainerFormatJpeg, strScreenPath);

The image captured is still either the local camera or the remote camera, not the mixing finial image show in the call window..

 

Its strange that there is only one window. If you check this:

screen_shot_2014-10-08_at_8.19.12_pm.jpg

It looks like the local camera is in a second window ...

Advertisement

Oh, sorry, the "Skype" means the "Skype UWP"/"Skype For Windows 10" version instead of the desktop version.

The strange thing is the "OutputWindow" is NULL.

Yeah that is strange, the spec says...

 

OutputWindow

Type: HWND

An HWND handle to the output window. This member must not be NULL.

 

Maybe that swap chain is invalid but then how you are able to get the surface...

 

 

You're looking at a DComp app. Yes, there are swapchains involved, but no individual surface in the app contains the entire contents of the window. The reason the HWND is null is because it's a composition swapchain, not a standard HWND swapchain. See the IDXGIFactory2 CreateSwapChain methods.

The only way to capture the contents of the app is to capture the desktop and isolate the app, or to capture the individual pieces of the app and re-composite them.

Hi SoldierOfLight, thanks for your reply.

Skype UWP doesn't use DComp libary since there is no according .dll found in the process.

Besides, it doesn't use  IDXGIFactory2 CreateSwapChain methods either, since I have hooked all the methods of IDXGIFactory2/IDXGISwapChainX, it just never called, only IDXGISwapChain is created.

Any ideas?

This topic is closed to new replies.

Advertisement