Sign in to follow this  

Dumping every frame to an image file

This topic is 674 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone,

 

I know this is quite an ugly way of doing video capture, but I'd like to be able to try the following in my DX9/C++ app:

 

- Force each frame in the program loop to represent a fixed time interval (e.g. 1/60th of a second - easy to do)

- Dump each frame to an external image file in a folder (I'd use a counter which is incremented in each frame to append a sequence number to the given frame's filename)

- Import each of these frames to a movie maker program in the knowledge that I am guaranteed a specific framerate

 

I've tried using programs such as Fraps and Camstudio to capture my screen, but the framerates are variable and often low. I'm simply making a demonstration video for my program, which doesn't even require realtime user interaction, so it doesn't matter how long it takes to render/save each frame in sequence.

 

Is there a way to save the frames like this? I'm using a windowed app too if that's a restriction. Perhaps you know an alternative way of saving each and every frame my program renders?

 

Thanks a lot!

Share this post


Link to post
Share on other sites

2 ways:

 

use a video encoder on the gpu

 

if your game is deterministic, which is a good idea, force the framerate and replay the input. That way you could render to a much larger framebuffer and capture 120Hz.

Share this post


Link to post
Share on other sites

Hey, thanks for the replies everyone:

 

- cozzie: Basically, my program is a demonstration of a simple autopilot program which is used to control a spacecraft in two dimensions. All I have to do is set the program running and the autopilot algorithm does the rest. Setting a fixed time-per-frame ensures the results are consistent and the autopilot is using a fixed timestep for each update. Hence there is no need for a good realtime framerate when I am capturing the video, I just need to make sure I can save every frame in sequence. So the answer to the second question is no - I like to render them on-screen so I can see what it's up to, but it's not totally necessary.

 

- Hodgman, harveypekar: I'll give those methods a go, thanks for the help :)

Share this post


Link to post
Share on other sites

This is the code that I use to take screenshots in-app. Note that if run in windowed mode it captures the entire desktop and cuts out the window area. This means that if some other window is put in front of your window it will capture that data as well.

LPDIRECT3DSURFACE9 CaptureScreen()
{
    UINT width;
    UINT height;
    if (IsFullscreen()) {
        width = GetDisplayWidth();
        height = GetDisplayHeight();
    }
    else {
        width = GetSystemMetrics(SM_CXSCREEN);
        height = GetSystemMetrics(SM_CYSCREEN);
    }

    LPDIRECT3DSURFACE9 pCaptureSurface;
    HRESULT hr = GetD3DDevice()->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCaptureSurface, NULL);
    if (FAILED(hr)) {
        SAFE_RELEASE(pCaptureSurface);
        return NULL;
    }

    hr = GetD3DDevice()->GetFrontBufferData(0, pCaptureSurface);
    if (FAILED(hr)) {
        SAFE_RELEASE(pCaptureSurface);
        return NULL;
    }

    return pCaptureSurface;
}

bool TakeScreenshot(const std::wstring& filename)
{
	LPDIRECT3DSURFACE9 pCaptureSurface = GetGraphicsDevice()->CaptureScreen();
	HRESULT hr = E_FAIL;
	if (pCaptureSurface != NULL) {
		D3DXIMAGE_FILEFORMAT imageFileFormat = D3DXIFF_JPG;
		std::wstring fileExtention = GXFile::GetFileExtention(filename);
		if (GXString::CompareNoCase(fileExtention.c_str(), L"bmp")) {
			imageFileFormat = D3DXIFF_BMP;
		}
		else if (GXString::CompareNoCase(fileExtention.c_str(), L"png")) {
			imageFileFormat = D3DXIFF_PNG;
		}

		if (GetGraphicsDevice()->IsFullscreen()) {
			hr = D3DXSaveSurfaceToFile(filename.c_str(), imageFileFormat, pCaptureSurface, NULL, NULL);
			if (FAILED(hr)) {
				GXLOG_WARN_F(L"Failed to save fullscreen screenshot to %s", filename.c_str());
			}
		}
		else {
			// Calculate the rectangle within the screen that the window is currently located.
			// I.e. 0,0 is top left of screen for all screens even on multi-monitor setups.
			RECT rcWindow;
			GetClientRect(m_hWnd, &rcWindow);
			POINT topPoint = {rcWindow.left, rcWindow.top};
			POINT bottomPoint = {rcWindow.right, rcWindow.bottom};
			ClientToScreen(m_hWnd, &topPoint);
			ClientToScreen(m_hWnd, &bottomPoint);
			rcWindow.left = topPoint.x;
			rcWindow.top = topPoint.y;
			rcWindow.right = bottomPoint.x;
			rcWindow.bottom = bottomPoint.y;
			for (unsigned int i = 0; i < m_displays.size(); i++) {
				RECT rcDest;
				if (IntersectRect(&rcDest, &m_displays[i].rect, &rcWindow)) {
					rcWindow.left -= m_displays[i].rect.left;
					rcWindow.top -= m_displays[i].rect.top;
					rcWindow.right -= m_displays[i].rect.left;
					rcWindow.bottom -= m_displays[i].rect.top;
					break;
				}
			}
			hr = D3DXSaveSurfaceToFile(filename.c_str(), imageFileFormat, pCaptureSurface, NULL, &rcWindow);
			if (FAILED(hr)) {
				GXLOG_WARN_F(L"Failed to save windowed screenshot to %s", filename.c_str());
			}
		}
		SAFE_RELEASE(pCaptureSurface);
	}
	return SUCCEEDED(hr);
}

Share this post


Link to post
Share on other sites

Saving pictures is anyway a good sourcing of a video material, you should be able to create some any HD /high frequency robust video encoded. I don't know about applications much, but VLC media player is amazing "player", can save/write to much any video format with possible settings, is open source, and I would not be surprised if it could read actual pictures and allow you for encoding any crazy 1GB large 3 second video or stuff.

Share this post


Link to post
Share on other sites

This topic is 674 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this