Read from video capture device deadlock - c++

I want capture image frame from video capture device on win7
and directly work with the RGB data.
The code is working but when device is off application is stuck.
I can't kill process. There are 2 devices to select webcam or a video capture device. With capDlgVideoSource sometimes a dialog opens and I can select one.
How to avoid a deadlock when device is off ?
How to put video frame data direcly in memory instead to a file ? Solved with frame copy to clipboard and then copy to memory
How can I explicitly set a device ?
The microsoft documentation is so less.
capDriverConnect(hCam, X) with X=1,2,3 doesnt work. 0 is right.
It seems "0" addresses both devices.
capDlgVideoSource(hCam); let me sometimes choose a driver in a dialog
sometimes not.
Sometimes without having asked for it mysteriously dialog pops up for selecting device sometimes not.
Please, can anybody help me to fix this unclear behaviour.
// create the preview window
HWND hCam = capCreateCaptureWindow(L"hoven", WS_CHILD, 0, 0, 0, 0, GetDesktopWindow(), 0);
if ( hCam == NULL )
{
printf("capCreateCaptureWindow Error !\n");
return -1;
}
// here I get deadlock
if ( !capDriverConnect(hCam, 0) )
{
printf("capDriverConnect Error !\n");
return -1;
}
capGrabFrame(hCam);
capFileSaveDIB(hCam, L"shot.bmp");
capDriverDisconnect(hCam);
DestroyWindow(hCam);
return 0;

Related

Cpp Detect connected monitor in windows 10

I have 2 projectors, usually disconnected from the electricity. For play videos I am using KODI to play videos. He has sources C++ available that I process for my needs.
When running KODI, I switch screens to extended mode.
SetDisplayConfig( 0, NULL, 0, NULL, SDC_TOPOLOGY_EXTEND | SDC_APPLY );
But this only works if both screens are detected by the system. In a situation where the screens are not detected by the system, I have to enter the display settings and click "detection" before running KODI.
How to do this detection in C++?
I tried:
bool IsDisplayConnected(int displayIndex)
{
DISPLAY_DEVICE device;
device.cb = sizeof(DISPLAY_DEVICE);
return EnumDisplayDevices(NULL, displayIndex, &device, 0);
}
IsDisplayConnected(0);
IsDisplayConnected(1);
But nothing is happening. The system does not try to detect the screens.

DirectX 11 GetDisplayModeList() fails in Remote Desktop Connection

Good afternoon,
I have a barebone Direct3D App that works on a host PC, but fails to initialize DirectX while running via remote desktop.
I traced the failure to this call, where it fails with
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
if(FAILED(result))
{
return false;
}
It fails with:
result = 0x887a0022 : A resource is not available at the time of the call, but may become available later.
The full initialization code is from Rastertek tutorials, found here:
http://www.rastertek.com/dx11tut03.html
Does anyone know a workaround for this problem?
Remote Desktop involves some corner-cases, and keep in mind it's sometimes using the 'Microsoft Basic Renderer' (a.k.a. the software WARP driver). See this blog post.
You can also guard your use of GetDisplayModeList in the remote scenario by detecting it in the first place. For example, the legacy DXUT sample framework did this in it's enumeration code:
// mode for the current screen resolution for the remote session.
if( 0 != GetSystemMetrics( SM_REMOTESESSION) )
{
DEVMODE DevMode;
DevMode.dmSize = sizeof( DEVMODE );
if( EnumDisplaySettings( nullptr, ENUM_CURRENT_SETTINGS, &DevMode ) )
{
NumModes = 1;
pDesc[0].Width = DevMode.dmPelsWidth;
pDesc[0].Height = DevMode.dmPelsHeight;
pDesc[0].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
pDesc[0].RefreshRate.Numerator = 0;
pDesc[0].RefreshRate.Denominator = 0;
pDesc[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
pDesc[0].Scaling = DXGI_MODE_SCALING_CENTERED;
}
}
You also can't use 'full-screen exclusive' mode in remote desktop:
if( GetSystemMetrics(SM_REMOTESESSION) != 0 )
{
sd.Windowed = TRUE;
}
You don't really need to use GetDisplayModeList at all. Just pick a reasonable starting size or start your window 'maximized'. See the directx-vs-templates for an approach that just uses the 'native resolution' of the desktop for both windowed and 'fake full screen'. It also all works well for remote desktop.
Another 'corner-case' with remote desktop is "raw input" for mouse. See the implementation of Mouse from the DirectX Tool Kit.
Not technically a solution, but the problem was in refresh rate initialization, bypassing this with a try{}-catch{} block allowed me to run with a default refresh rate via remote desktop. Everything else initialized without issues

Video Recording Hangs on IMFSinkWriter->Finalize();

I have an issue when finalizing a video recording into an .mp4 using Media Foundation where the call to IMFSinkWriter->Finalize(); hangs forever. It doesn't always happen, and can happen on almost any machine (seen on Windows server, 7, 8, 10). Flush() is called on the audio and video streams before hand and no new samples are added between Flush and Finalize. Any ideas on what could cause Finalize to hang forever?
Things I've tried:
Logging all HRESULTs to check for any issues (was already checking them before proceeding to the next line of code)
Everything comes back as S_OK, not seeing any issues
Added the IMFSinkWriterCallback on the stream to get callbacks when
the stream process markers (adding markers every 10 samples) and finishes Finalize()
Haven't been able to reproduce since adding this but this would give the best information about what's going on when I get it working.
Searched code samples online to see how others are setting up the
Sink Writer and how Finalize() is used
Didn't find many samples and it looks like my code is similar to the ones that were found
Looked at encoders available and used by each system including version of the encoder dll
Encoders varied between AMD H.264 Hardware MFT Encoder and H264 Encoder MFT on machines that could reproduce the issue. Versions didn't seem to matter and some of the machines were up to date with video drivers.
Here are some code samples without any HRESULT checking (that doubled the amount of code so I took it out)
Building the sink sample:
CComPtr<IMFAttributes> pAttr;
::MFCreateAttributes( &pAttr, 4 );
pAttr->SetGUID( MF_TRANSCODE_CONTAINERTYPE, GetFileContainerType() );
pAttr->SetUINT32( MF_LOW_LATENCY, FALSE ); // Allows better multithreading
pAttr->SetUINT32( MF_SINK_WRITER_DISABLE_THROTTLING, TRUE ); // Does not block
pAttr->SetUINT32( MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE );
m_pCallback.Attach( new MFSinkWriterCallback() );
pAttr->SetUnknown( MF_SINK_WRITER_ASYNC_CALLBACK, m_pCallback );
::MFCreateSinkWriterFromURL( m_strFilename.c_str(), NULL, pAttr, &m_pSink );
if ( m_pVideoInputType && m_pVideoOutputType )
{
m_pSink->AddStream( m_pVideoOutputType, &m_dwVideoStreamId );
// Attributes for encoding?
CComPtr<IMFAttributes> pAttrVideo;
// Not sure if these are needed
//::MFCreateAttributes( &pAttrVideo, 5 );
m_pSink->SetInputMediaType( m_dwVideoStreamId, m_pVideoInputType, pAttrVideo );
}
if ( m_pAudioInputType && m_pAudioOutputType )
{
m_pSink->AddStream( m_pAudioOutputType, &m_dwAudioStreamId );
// Attributes for encoding?
CComPtr<IMFAttributes> pAttrAudio;
// Not sure if these are needed
//::MFCreateAttributes( &pAttrAudio, 2 );
//pAttrAudio->SetGUID( MF_MT_SUBTYPE, MFAudioFormat_AAC );
//pAttrAudio->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, 16 );
m_pSink->SetInputMediaType( m_dwAudioStreamId, m_pAudioInputType, pAttrAudio );
}
m_pSink->BeginWriting();
Stopping the recording sample:
if ( m_dwVideoStreamId != (DWORD)-1 )
{
m_sink->Flush( m_dwVideoStreamId );
}
if ( m_dwAudioStreamId != (DWORD)-1 )
{
m_sink->Flush( m_dwAudioStreamId );
}
m_sink->Finalize();
There is a lot of situation where a Media Foundation application can hang :
Calling MFShutDown/CoUninitialize when using Media Foundation objects.
Using a GUI, and doing bad use of windows message pump in multithreaded application.
Bad use of MTA/STA components.
Bad use of critical section/wait for event function.
Forget to call EndXXX() function when BeginXXX() function are used.
Bad use of Callback function.
Forget to call AddRef when necessary, and releasing the object used by another thread.
A bug in Media Foundation (there are some on Windows Seven).
and so on...
When i say a minimal source code, i mean, isolate the source code that do the encoding process, and provide it to Github if it's too large. It's better if we can compile and try the source code, because deadlock are difficult to find.

Change 2nd Monitor Display Setting to Duplicate

I am attempting to programatically make the 2nd Monitor have a duplicate display. My function below should change the 2nd monitors display to 'duplicate display', ie, make the 2nd monitor display everything that is on the 1st/Primary monitor.
My Problem: When I run my function it successfully finds the 2nd monitor and it changes that monitors display x coordinate to 0, ie, the left of the primary monitor screen by changing the DEVMODE dmPosition.x property. Both of my 2 monitors refresh themselves(they go black then reshow their screen) but the 2nd monitor still has the extended display instead of a duplicate display.
Any ideas how I can make my 2nd Monitor have a duplicate display?
Some relevant information:
- My 2nd monitor is a LCD TV and is connected to my laptop via HDMI
- My function code is exacty the same as the example on this MSDN Page that describes how to attach a 2nd monitor without having to restart. I have changed LINE 30 though.
- I am aware I can change the display on Windows 7 using one WinAPI function call but I need my program to work on Windows 2000 and up.
// From http://support.microsoft.com/kb/308216/en-gb Title: You must restart...
BOOL TVManager::AddUnattachedDisplayDeviceToDesktop()
{
DWORD DispNum = 0;
DISPLAY_DEVICE DisplayDevice;
DEVMODE defaultMode;
HDC hdc;
int nWidth;
BOOL bFoundSecondary = FALSE;
hdc = GetDC(0);
nWidth = GetDeviceCaps(hdc, HORZRES);
ReleaseDC(0, hdc);
// Initialize DisplayDevice.
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);
// Get display devices.
while ((EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0)) && (bFoundSecondary == FALSE))
{
ZeroMemory(&defaultMode, sizeof(DEVMODE));
defaultMode.dmSize = sizeof(DEVMODE);
if (!EnumDisplaySettings((LPTSTR)DisplayDevice.DeviceName, ENUM_REGISTRY_SETTINGS, &defaultMode)) {
printf("1\n");
return FALSE; // Store default failed
}
if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) {
//Found the first secondary device.
_tprintf(_T("Found the first secondary device: Name: %s, Pos: %d, Width: %d\n"), DisplayDevice.DeviceName, defaultMode.dmPosition.x, nWidth);
bFoundSecondary = TRUE;
defaultMode.dmPosition.x = 0; // LINE CHANGED: ONLY CHANGE FROM MSDN'S CODE
defaultMode.dmFields = DM_POSITION;
ChangeDisplaySettingsEx((LPTSTR)DisplayDevice.DeviceName, &defaultMode, NULL, CDS_NORESET|CDS_UPDATEREGISTRY, NULL);
_tprintf(_T("Check for error: %u\n"), GetLastError()); // prints "Check for error: 0" which means no error occurred
// A second call to ChangeDisplaySettings updates the monitor.
ChangeDisplaySettings(NULL, 0);
_tprintf(_T("Check for error: %u\n"), GetLastError()); // prints "Check for error: 0" which means no error occurred
}
// Reinitialize DisplayDevice.
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);
DispNum++;
} // End while the display devices.
return TRUE;
}
Windows XP and earlier uses a different display driver model (XPDM) from Vista and later (WDDM). Mirroring on XPDM depends very much on your graphics card vendor. The general idea is that for extending the desktop, you provide an extend driver; for mirroring a portion of the desktop, you provide a mirror driver.
In most cases, each extend driver is responsible for one output on your graphics card. Let's say that you have a dual DVI card, then you should see two extend drivers in your Device Manager, each is responsible for one of the DVI port. When you want to set your monitor to extend the desktop, you enable the extend driver and give it a sensible location.
Mirroring is trickier. This is where the behaviour can vary a bit between the different card vendors. From the perspective of the OS, this is what's happening. The extend driver associated with the graphics card port is disabled. The mirror driver is enabled if it was not enabled already. The mirror driver is then placed at (0, 0). Then some trickery happens inside your graphics card/driver and the monitor is showing what's inside the mirror driver's screen buffer.
In order to set a monitor into mirror mode on XPDM, you need find the extend driver it's currently showing stuff from and disable it. This may be all you have to do. Some of the vendors will automatically do the rest for you and start mirroring the primary display. Some vendors will do whatever your monitor was doing last before it was put into extend mode. If you find your monitor not showing anything, you can try to enable the mirror driver. If you manage to find the mirror driver and enable it, what happens after is anyone's guess. There isn't a universal way to wire up a monitor to a mirror driver.

How do you exit X11 program without Error

I have a fairly simple "Hello World" in X11 at end of question. But when it exits I get the run time error messages below:
$ ./xtest
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 9 requests (7 known processed) with 0 events remaining.
So I tried handling the wmDeleteMessage myself, and I was able to stop the window from closing, so i know I am getting the event correctly. Than I added a XDestroyWindow() to the event handling and I get new errors.
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 4 (X_DestroyWindow)
Resource id in failed request: 0x130
Serial number of failed request: 12
Current serial number in output stream: 12
It sounds like i am trying to destroy a already destroyed Window, but if I take out the XDestroyWindow() it stays alive on my screen.
Below is my code with an attempt at a destroy window handler. How do I exit without any errors?
#include<X11/Xlib.h>
#include <iostream>
int main()
{
Display *display;
if(!(display=XOpenDisplay(NULL)))
{
std::cerr << "ERROR: could not open display\n";
return 1;
}
int screen = DefaultScreen(display);
Window rootwind = RootWindow(display, screen);
Colormap cmap = DefaultColormap(display, screen);
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
int blackColor = BlackPixel(display, screen);
int whiteColor = WhitePixel(display, screen);
Window w = XCreateSimpleWindow(display, rootwind, 0, 0, 200, 100, 0, blackColor, blackColor);
XMapWindow(display, w);
XSetWMProtocols(display, w, &wmDeleteMessage, 1);
bool running = true;
while(running)
{
XEvent e;
XNextEvent(display, &e);
switch (e.type)
{
case ClientMessage:
if(e.xclient.data.l[0] == wmDeleteMessage)
{
std::cout << "Shutting down now!!!" << std::endl;
XDestroyWindow(display,e.xdestroywindow.window);
running=false;
break;
}
break;
}
}
XCloseDisplay(display);
return 0;
}
Update
Changed line to :
std::cout << "Shutting down now!!!" << std::endl;
XDestroyWindow(display,w);
Which I don't like because I plan on having more than window, but for now I am
back to the first error message I had :
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 9 requests (7 known processed) with 0 events remaining.
Update
Tried changing many things around like having the loop run off of XPending().
Decided to run someone else's hello world and I get the same problem with their code. Must be something wrong with my setup.
Update
Apparently alot of people have this problem. Google ftk had this problem and they fixed it in their change log. They call FTK_QUIT() which i am guessing is like Exit(). So i put my return right there inside the loop and that solved the problem. Not sure why but it did. fixed code:
case ClientMessage:
if(e.xclient.data.l[0] == wmDeleteMessage)
{
XDestroyWindow(display,e.xclient.window);
XCloseDisplay(display);
return 0;
}
Will still give correct answer to someone who can explain why and if is possible move the return statement (along with the XCloseDisplay) outside of the loop.
The Event loop should look like this to exit properly:
XEvent e;
do
{
XNextEvent(display, &e);
if(e.type == ClientMessage && e.xclient.data.l[0] == wmDeleteMessage)
{
XDestroyWindow(display,e.xclient.window);
break;
}
//...
}while (XPending(display) > 0)
XCloseDisplay(display);
return 0;
When running in a switch statement the code does not work. Even if it exits the loop without calling another X function. The if statement above placed before your switch statement fixes the issue without returning from the program inside the loop.
The solution to this problem is straightforward:
You must use the right structure member with the XDestroyWindow() function.
Due to the implementation standard of the X11 event structures, they're very similar each other. Every structure begins with the 'type' member, and the first members are practically always the same.
Now assume:
int = 4 bytes
Bool = 4 bytes
unsigned long = 8 bytes
Display* = 8 bytes
Window = 4 bytes
If you call XDestroyWindow() with e.xdestroywindow.window, you are going to be 28 bytes away from the beginning of the event structure, while if you use e.xclient.window, you would be 24 bytes away.
Since you're going to call XDestroyWindow() with a wrong Window argument, it will fail. Instead if you call it using e.xdestroywindow.event (which is 24 bytes away from the beginning of the event structure), the address would be right and the function would work gracefully.
If you take a look yourself at the Xlib.h file, you'll notice that the two structures have the window element positioned differently.
Stated this, remember that Xlib has been developed for years and many programmers every day work with it, so if there is a mysterious error, it's probably not within Xlib. As a last hint I want to tell you: if you want to get farther with Xlib programming, always take the header files as the primary reference, followed by the system manual, then all the rest.
The only error with your code in the end is:
XDestroyWindow(display,e.xdestroywindow.window);
Which must be changed to this:
XDestroyWindow(display,e.xclient.window);
Instead the usage of switch is good, and is the most implemented, with no issues on the X11 code.
NOTE: I've tested your code myself, by changing that line only, and then doing various tests, printing the result. The XDestroyWindow() line is for sure the only error.
Just call XDestroyWindow() right before XCloseDisplay().
Edit:
Sorry, I didn't understand the XSetWMProtocols thing. Now I've read up on it. I think you're accessing the wrong member of the event union.
XDestroyWindow(display,e.xdestroywindow.window);
Should probably be:
XDestroyWindow(display,e.xclient.window);
I had the same problem, and after digging through Xlib documentation and a lot of experimenting I think I know the answer to your question and I can explain it to you.
When you call XCreateWindow or XCreateSimpleWindow and then XMapWindow, you instruct the X Server to create your window and map in onto the screen. After sending these commands from the local buffer to the server (by calling XFlush or any function which requests some data from the server, since it implicitly flushes the command buffer), the X Server displays your window. Then it's a job of the Window Manager to attach all the decorations to your window, e.g. some borders, title bar, window menu and those buttons to minimize/maximize/close the window.
Now your window is being displayed, and after a while you can decide to destroy it with XDestroyWindow and close the connection to the X Server by calling XCloseDisplay, and everything will be fine, no errors.
The problem is that when the user clicks on that X on your window's title bar, it is not the job of the X Server to handle it, but the Window Manager's job (the X Server knows nothing about those decorations and it doesn't care). The usual reaction of the Window Manager when the user closes the top-level window of your program is to destroy the window and close the connection to the X Server, because that's what most users would expect. Your program may still run off-screen, but the top-level window is usually associated with the X Server connection by the Window Manager.
So when the Window Manager destroys your window, you cannot call XDestroyWindow, because the window is already destroyed and its Window handle is invalid. You will get an error about BadWindow. You also cannot call XCloseDisplay, because the connection to the X Server is already closed, and this will cause the XIO: fatal IO error 11 (Resource temporarily unavailable) on X server error many users experience from applications whose authors didn't knew that. It is a common mistake, because in one hand you are encouraged to clean up after yourself, but in the other hand the documentation is misleading about how this should be done properly.
There is a convention, though, about how X Server and Window Manager should cooperate, which also covers responding to user's commands to close the top-level window. There's an extension to the X protocol that handles it. Here's how the Xlib documentation explains it:
Clients, usually those with multiple top-level windows, whose server connection must survive the deletion of some of their top-level windows, should include the atom WM_DELETE_WINDOW in the WM_PROTOCOLS property on each such window. They will receive a ClientMessage event as described above whose data[0] field is WM_DELETE_WINDOW.
[...]
Clients that choose not to include WM_DELETE_WINDOW in the WM_PROTOCOLS property may be disconnected from the server if the user asks for one of the client's top-level windows to be deleted.
So there are two solutions to this problem: either avoid calling XDestroyWindow and XCloseDisplay when your window is being closed by the Window Manager and not by yourself (you actually don't have to clean up the top-level window since the X Server will destroy it nevertheless when your program ends), or you need to register the WM_DESTROY_WINDOW extension and wait for notification from the Window Manager when it is instructed by the user to close your window (it will send you a ClientMessage event then, with its data[0] set to WM_DELETE_WINDOW). And after receiving it just destroy the window and close the connection to the X Server yourself, and end your program. Or leave the connection to the X Server open to perform some more communication with it if you wish. When you handle WM_DESTROY_WINDOW, the Window Manager will not try to destroy your window nor close the connection to the X Server.
// this code from : https://en.wikibooks.org/wiki/X_Window_Programming/Xlib don't show error...
/*
Simple Xlib application drawing a box in a window.
To Compile: gcc -o test test.c -lX11 */
#include<X11/Xlib.h>
#include<stdio.h>
#include<stdlib.h> // prevents error for exit on line 18 when compiling with gcc
int main() {
Display *d;
int s;
Window w;
XEvent e;
/* open connection with the server */
d=XOpenDisplay(NULL);
if(d==NULL) {
printf("Cannot open display\n");
exit(1);
}
s=DefaultScreen(d);
/* create window */
w=XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
BlackPixel(d, s), WhitePixel(d, s));
// Process Window Close Event through event handler so XNextEvent does Not fail
Atom delWindow = XInternAtom( d, "WM_DELETE_WINDOW", 0 );
XSetWMProtocols(d , w, &delWindow, 1);
/* select kind of events we are interested in */
XSelectInput(d, w, ExposureMask | KeyPressMask);
/* map (show) the window */
XMapWindow(d, w);
/* event loop */
while(1) {
XNextEvent(d, &e);
/* draw or redraw the window */
if(e.type==Expose) {
XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
}
/* exit on key press */
if(e.type==KeyPress)
break;
// Handle Windows Close Event
if(e.type==ClientMessage)
break;
}
/* destroy our window */
XDestroyWindow(d, w);
/* close connection to server */
XCloseDisplay(d);
return 0;
}