Frame grabbing with Matrox - c++

I'm trying to run Matrox Image Library's example code for frame grabbing. When the application runs, all I get is a black screen for the display image.
I know my configuration is correct, since when I try Matrox Intellicam software, I'm able to grab an image, which makes it more weird. It's just something in the software I need to change that I'm not aware of.
I've found this, but it was not helpful really. Frame Capture using Matrox Commands
This is the code I have.
/* Allocate 2 display buffers and clear them. */
MbufAlloc2d(MilSystem,
(MIL_INT)(MdigInquire(MilDigitizer[0], M_SIZE_X, M_NULL)*GRAB_SCALE),
(MIL_INT)(MdigInquire(MilDigitizer[0], M_SIZE_Y, M_NULL)*GRAB_SCALE),
8L+M_UNSIGNED,
M_IMAGE+M_GRAB+M_PROC+M_DISP, &MilImageDisp[0]);
MbufClear(MilImageDisp[0], 0x0);
MbufAlloc2d(MilSystem,
(MIL_INT)(MdigInquire(MilDigitizer1, M_SIZE_X, M_NULL)*GRAB_SCALE),
(MIL_INT)(MdigInquire(MilDigitizer1, M_SIZE_Y, M_NULL)*GRAB_SCALE),
8L+M_UNSIGNED,
M_IMAGE+M_GRAB+M_PROC+M_DISP, &MilImageDisp1);
MbufClear(MilImageDisp1, 0x80);
/* Display the buffers. */
MdispSelect(MilDisplay[0], MilImageDisp[0]);
MdispSelect(MilDisplay[1], MilImageDisp[1]);
/* Grab continuously on displays at the specified scale. */
MdigControl(MilDigitizer[0], M_GRAB_SCALE, GRAB_SCALE);
MdigGrabContinuous(MilDigitizer[0],MilImageDisp[0]);
MdigControl(MilDigitizer[1], M_GRAB_SCALE, GRAB_SCALE);
MdigGrabContinuous(MilDigitizer[1],MilImageDisp[1]);
I'm quite stuck and I would appreciate any idea that suggests what might be wrong.

Frame grabber loses synchronization because either no default digitizer format is set or it's not the correct format for the camera.
To solve this issue, either set the DCF in code or manually in config file.

Related

C++ - Display continuously updating image

I have written a pathtracer in C++, and now I want to display the rendering process in real time, so I'm wondering what the simplest/best way to do this is.
Basically, the rendered image updates after every iteration, so I just need to retrieve it, display it in a separate window, and update it.
I was thinking about using DirectX, and it seems that I could probably also do it with OpenCV, but I'm just looking for a simple way which doesn't require adding a lot of new code.
I am using C++ on Windows.
If I understand correctly your path tracer probably outputs a color per emitted ray? If that is the case, and you are thinking about displaying the rendered image in a separate window I'd suggest using SDL2. There's a great set of tutorials concerning real-time graphics using C++ and SDL by Lazy Foo' Productions.
Excerpt taken from official SDL documentation (without cruft needed to initialize windows) regarding SDL_Surface, which you will probably be using:
/* This is meant to show how to edit a surface's pixels on the CPU, but
normally you should use SDL_FillRect() to wipe a surface's contents. */
void WipeSurface(SDL_Surface *surface)
{
/* This is fast for surfaces that don't require locking. */
/* Once locked, surface->pixels is safe to access. */
SDL_LockSurface(surface);
/* This assumes that color value zero is black. Use
SDL_MapRGBA() for more robust surface color mapping! */
/* height times pitch is the size of the surface's whole buffer. */
SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
SDL_UnlockSurface(surface);
}

Using Media Foundation to encode Direct X surfaces

I'm trying to use the MediaFoundation API to encode a video but I'm having problems pushing the samples to the SinkWriter.
I'm getting the frames to encode through the Desktop Duplication API. What I end up with is an ID3D11Texture2D with the desktop image in it.
I'm trying to create an IMFVideoSample containing this surface and then push that video sample to a SinkWriter.
I've tried going about this in different ways:
I called MFCreateVideoSampleFromSurface(texture, &pSample) where texture is the ID3D11Texture2D, filled in the SampleTime and SampleDuration and then passed the created sample to the SinkWriter.
SinkWriter returned E_INVALIDARG.
I tried creating the sample by passing nullptr as the first argument and creating the buffer myself using MFCreateDXGISurfaceBuffer, and then passing the resulting buffer into the Sample.
That didn't work either.
I read through the MediaFoundation documentation and couldn't find detailed information on how to create the sample out of a DirectX texture.
I ran out of things to try.
Has anyone out there used this API before and can think of things I should check, or of any way on how I can go about debugging this?
First of all you should learn to use mftrace tool.
Very likely, it will tell you the problem right away.
But my guess is, following problems are likely.
Probably, some other attributes are required besides SampleTime / SampleDuration.
Probably, SinkWriter needs a texture it can read on CPU. To fix that, when a frame is available, create a staging texture of the same format + size, call CopyResource to copy desktop to staging texture, then pass that staging texture to MF.
Even if you use a hardware encoder so the CPU never tries to read the texture data, I don’t think it’s a good idea to directly pass your desktop texture to MF.
When you set a D3D texture for sample, no data is copied anywhere, the sample merely retains the texture.
MF works asynchronously, it may buffer several samples in its topology nodes if they want to.
DD gives you data synchronously, you may only access the texture between AcquireNextFrame and ReleaseFrame calls.

Accessing a Projector using MATlab

I wish to display an image through my projector via MATlab. The projected image should be full sized without any figure handle bars (menu bar, the grey stuff which encompasses a figure etc).
Similar to a normal presentation when the projector projects the complete slide or image, I want to do the same using MATlab as my platform. Any thoughts or idea? Can we access the projector using MATlab? My first thoughts were to send data to the corresponding printer IP but that doesn't seem to work :/
If you know the relevant C++ command or method to do this, please suggest a link or a library, so that I may try and import it on my MATlab platform.
Reason for doing this: Projector-Camera calibration for photo-metric correction of my projector display output.
Assuming your projector is set as a second display, you can do something very simple. Get the monitor position information and set the figure frame to be the monitor size
// plot figure however you want
monitorFrames = get(0,'MonitorPositions');
secondMonitor = monitorFrames(2,:);
secondMonitor(3) = secondMonitor(3)-monitorFrames(1,3);
set(gcf,'Position',secondMonitor);
This will put the figure window onto the second monitor and have it take up the whole screen.
You can then use this to do whatever calibration you need, and shift this window around as necessary.
NOTE:
In no way am I saying this is the ideal solution. It is quick and dirty, and will not use any outside libraries.
UPDATE
If the above solution does not suit your specific needs, what you could always do is save the plot as an image, then have your MATLAB script, call a c++ script that opens the image and makes it full screen.
This is non-trivial. For Windows you can use the WindowAPI submission to the MATLAB File Exchange. With the WindowAPI function installed you can do
WindowAPI(FigH, 'Position', 'full');
For Mac and Linux you can use wrappers around OpenGL to do low level plotting, but you cannot use standard MATLAB figure windows. One nice implementation is PsychToolbox.

Whole screen capture and render in DirectX [PERFORMANCE]

I need some way to get screen data and pass them to DX9 surface/texture in my aplication and render it at at least 25fps at 1600*900 resolution, 30 would be better.
I tried BitBliting but even after that I am at 20fps and after loading data into texture and rendering it I am at 11fps which is far behind what I need.
GetFrontBufferData is out of question.
Here is something about using Windows Media API, but I am not familiar with it. Sample is saving data right into file, maybe it can be set up to give you individual frames, but I haven't found good enough documentation to try it on my own.
My code:
m_memDC.BitBlt(0, 0, m_Rect.Width(),m_Rect.Height(), //m_Rect is area to be captured
&m_dc, m_Rect.left, m_Rect.top, SRCCOPY);
//at 20-25fps after this if I comment out the rest
//DC,HBITMAP setup and memory alloc is done once at the begining
GetDIBits( m_hDc, (HBITMAP)m_hBmp.GetSafeHandle(),
0L, // Start scan line
(DWORD)m_Rect.Height(), // # of scan lines
m_lpData, // LPBYTE
(LPBITMAPINFO)m_bi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // Use RGB for color table
//at 17-20fps
IDirect3DSurface9 *tmp;
m_pImageBuffer[0]->GetSurfaceLevel(0,&tmp); //m_pImageBuffer is Texture of same
//size as bitmap to prevent stretching
hr= D3DXLoadSurfaceFromMemory(tmp,NULL,NULL,
(LPVOID)m_lpData,
D3DFMT_X8R8G8B8,
m_Rect.Width()*4,
NULL,
&r, //SetRect(&r,0,0,m_Rect.Width(),m_Rect.Height();
D3DX_DEFAULT,0);
//12-14fps
IDirect3DSurface9 *frameS;
hr=m_pFrameTexture->GetSurfaceLevel(0,&frameS); // Texture of that is rendered
pd3dDevice->StretchRect(tmp,NULL,frameS,NULL,D3DTEXF_NONE);
//11fps
I found out that for 512*512 square its running on 30fps (for i.e. 490*450 at 20-25) so I tried dividing screen, but it didn't seem to work well.
If there is something missing in code please write, don't vote down. Thanks
Starting with Windows 8, there is a new desktop duplication API that can be used to capture the screen in video memory, including mouse cursor changes and which parts of the screen actually changed or moved. This is far more performant than any of the GDI or D3D9 approaches out there and is really well-suited to doing things like encoding the desktop to a video stream, since you never have to pull the texture out of GPU memory. The new API is available by enumerating DXGI outputs and calling DuplicateOutput on the screen you want to capture. Then you can enter a loop that waits for the screen to update and acquires each frame in turn.
To encode the frames to a video, I'd recommend taking a look at Media Foundation. Take a look specifically at the Sink Writer for the simplest method of encoding the video frames. Basically, you just have to wrap the D3D textures you get for each video frame into IMFSample objects. These can be passed directly into the sink writer. See the MFCreateDXGISurfaceBuffer and MFCreateVideoSampleFromSurface functions for more information. For the best performance, typically you'll want to use a codec like H.264 that has good hardware encoding support (on most machines).
For full disclosure, I work on the team that owns the desktop duplication API at Microsoft, and I've personally written apps that capture the desktop (and video, games, etc.) to a video file at 60fps using this technique, as well as a lot of other scenarios. This is also used to do screen streaming, remote assistance, and lots more within Microsoft.
If you don't like the FrontBuffer, try the BackBuffer:
LPDIRECT3DSURFACE9 surface;
surface = GetBackBufferImageSurface(&fmt);
to save it to a file use
D3DXSaveSurfaceToFile(filename, D3DXIFF_JPG, surface, NULL, NULL);

Recording and Saving the Screen using C++ on Windows

I'm trying to write an application that records and saves the screen in C++ on the windows platform. I'm not sure where to start with this. I assume I need some sort of API, (FFMPEG, maybe OpenGL?). Could someone point me in the right direction?
You could start by looking at Windows remote desktop protocol, maybe some programming libraries are provided for that.
I know of a product that intercepts calls into the Windows GDI dll and uses that to store the screen drawing activities.
A far more simpler approach would be to do screenshots as often as possible and somehow minimize redundant data (parts of the screen that didn't change between frames).
If the desired output of your app is a video file (like mpeg) you are probably better off just grabbing frames and feeding them into a video encoder. I don't know how fast the encoders are these days. Ffmpeg would be a good place to start.
If the encoder turns out not fast enough, you can try storing the frames and encoding the video file afterwards. Consecutive frames should have many matching pixels, so you could use that to reduce the amount of data stored.