OpenCV: setting a timeout to wait for a frame in the VideoCapture class
Who cares - I ask for a cat.
Research
With the help of Google, it was found that this problem rests on ffmpeg - there are callbacks that provide information about disconnecting. A timeout of 30 seconds was set in pull request # 6053. The problem was added as follows: at the moment, the cmake-collector downloads the opencv_ffmpeg.dll file instead of assembling it in place, and the assembly instructions with ffmpeg have disappeared. Code with timeout constants (which, at least on Windows does not compile in any way) is located in the modules / videoio / src / cap_ffmpeg_impl.hpp file:
#define LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS 30000#define LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS 30000The task, thus, was formed as follows:
- Make this file build under Windows;
- Change constants in it;
- Make sure there are no problems at work.
Without thinking twice, I will talk about how it was solved. First you need to download the latest development version of ffmpeg with the header files, dll, and lib, and put it all in the right places in source / 3rdparty - for the sake of convenience, you can actually put it anywhere. Next, you need to make the following changes to the OpenCV source files:
modules / videoio / src / cap_ffmpeg.cpp:
Comment out lines in the inclusions regarding the potential inclusion of cap_ffmpeg_api.hpp
//#if defined HAVE_FFMPEG && !defined WIN32#include"cap_ffmpeg_impl.hpp"//#else//#include "cap_ffmpeg_api.hpp"//#endifIn icvInitFFMPEG () function
...
#ifdef WIN32...//все закомментировать, включая директивы препроцессора#elif defined HAVE_FFMPEG//оставить только то, что есть внутри#endif
...What happened here - we abandoned the use of ffmpeg functionality loading from opencv_ffmpeg.dll using LoadLibrary, and switched to the internal implementation, which is located inside the cap_ffmpeg_impl.hpp file.
modules / videoio / src / cap_ffmpeg_impl.hpp:
Find the above constants, change them to the desired ones. In my case -
#define LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS 2000#define LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS 1000This file, in general, was not created for assembly under Windows, therefore, some of the functionality required to compile it is missing in it - we are talking about snprintf. The code was pulled from somewhere with StackOverflow. Paste in any convenient place.
#if defined(_MSC_VER) && _MSC_VER < 1900#define snprintf c99_snprintf#define vsnprintf c99_vsnprintf
__inlineintc99_vsnprintf(char *outBuf, size_t size, constchar *format, va_list ap){
int count = -1;
if (size != 0)
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
__inlineintc99_snprintf(char *outBuf, size_t size, constchar *format, ...){
int count;
va_list ap;
va_start(ap, format);
count = c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#endifAfter making the changes, you need to force all this stuff to compile. To get started, you need to generate * .sln for OpenCV using CMake. An attempt to build opencv_videoio at the moment will not work. Correctable. Open the Visual Studio project for the videoio module: build / modules / videoio / opencv_videoio.sln. Add ffmpeg header files to include directories, add it * .lib to the link.
As soon as opencv_videoio is built, this dll can be easily laid in place of the "standard" one. Remember that now all the dlls from the ffmpeg delivery will also be needed to work - the application will not work without them.
An important point: now, for this to work, cv :: CAP_FFMPEG must be specified as the VideoCapture backend.
The result at the moment is the flight is normal, I did not notice any bugs for the month. However, given all of the above, they are more than possible, so use only at your own peril and risk. If there are other ways to achieve the desired, as I said, I will be very glad to listen.
Thanks for attention.