views:

89

answers:

1

In follow up to my previous question, I am able to save the backbuffer of a Direct3DDevice to a surface.

I already found the D3DXSaveSurfaceToFile in the DirectX SDK and it works fine! However, I want to record the obtained surfaces to an AVI file.

I also found the AVIFile reference but they are obviously not straight up compatible with DirectX surfaces.

What would be the best way of approaching this problem? I've seen a number of GDI+/MVC based solutions of grabbing HDCs but those are out of the question. I'm also not sure what kind of data AVIFile expects and how to extract it from the D3DSurface.

Please advise! :)

edit:

Post-processing is also an option. I can capture the surface data in a number of formats, specified here, into memory with D3DXSaveSurfaceToFileInMemory. Afterwards, I could compress this data and then store to disk.

How should I be compressing my data? How should I be storing it? Do I store a timestamp along with it? After recording, how should I turn the generated data into an AVI file?

+1  A: 

The source code at this link will show you how to do it:

http://gpalem.web.officelive.com/SimulationRecording.html

Edit: Well you don't have to do things exactly like that linked code. You have a D3DSurface so you can just lock it grab the bits and pass them into CAviFile::AppendFrameUsual ... If you want to change its format then use D3DXLoadSurfaceFromSurface. I didn't say the link was a perfect solution but it DOES show you how to write the frames into an AVi file.

Edit2: As I didn't answer your edit I should do. Firstly don't bother with compression until you have got uncompressed working. Compression is a significantly more complicated thing to get right and you won't be able to get proper compression by simply using the various D3DXSurface copying functions. They don't support the kinds of compression you are after. D3DX is for 3D rendering and NOT for video compression.

For video compression you are best off using DirectShow as you can, simply, add any compressors you wish. This will however mean you'll need to write a "source filter" that you can build your graph off. DirectShow is not an easy thing to use but its very powerful. As far as writing the "source filter" goes you can check out the "Push Source" example in the windows SDK. You will need to adapt it to take the data you are retrieving however.

As an aside, going further on my original edit you could use that code as is by intercepting more D3D9 calls. If you hook the SetRenderTarget calls then you can insert whatever render target you like in there and use the, previously, linked code directly ...

Goz
I had a look at this and it involves changing the rendering target, and then copying back the backbuffer. That's not a possibility for me, since I'm just hooking API's and have no control over the original backbuffer. I can obtain the current backbuffer and feed it to something just fine though.
Daniel
Also, it requires me to hook into CreateDevice/Reset/etc, which I don't really want to do (would put restrictions on when I should start injecting / hooking).
Daniel
@Daniel: Updated my answer.
Goz
@Goz: Even if I were to hook those calls, I'd still not have any way to copy back the data into the original backbuffer... Preferably I'd just want an easy way to turn a bunch of bitmaps into AVI files.
Daniel
@Daniel: Why would you want to copy data BACK into the backbuffer? That would be a TERRIBLE thing to do indeed! You should definitely avoid doing it ...
Goz
@Goz: "Since all the rendering is done on the CDxToMovie's internal render target, your application's back surface would not be having any valid content to display in your application window." ... ... "To avoid this, you can optionally copy back the CDxToMovie's internal render target content onto your application's back surface"
Daniel
That being said, I guess I'll just have to hook at an earlier time. Accepting for your efforts.
Daniel
@Daniel: Bear in mind that you don't NEED to use their render buffer idea. Teh example code shows yo uhow to write an AVI. The data to send to that AVI could come from anywhere ... Including a D3DSurface gained from D3DXSaveSurfaceToFileInMemory.
Goz