diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index a574232f27..74da1d0df9 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -638,7 +638,7 @@ public: implementation if multiple are available: e.g. cv::CAP_FFMPEG or cv::CAP_IMAGES or cv::CAP_DSHOW. @sa The list of supported API backends cv::VideoCaptureAPIs */ - CV_WRAP VideoCapture(const String& filename, int apiPreference = CAP_ANY); + CV_WRAP explicit VideoCapture(const String& filename, int apiPreference = CAP_ANY); /** @overload @brief Opens a camera for video capturing @@ -650,7 +650,7 @@ public: @sa The list of supported API backends cv::VideoCaptureAPIs */ - CV_WRAP VideoCapture(int index, int apiPreference = CAP_ANY); + CV_WRAP explicit VideoCapture(int index, int apiPreference = CAP_ANY); /** @brief Default destructor diff --git a/modules/videoio/src/cap.cpp b/modules/videoio/src/cap.cpp index 6ae9ac700b..c4206fbfbd 100644 --- a/modules/videoio/src/cap.cpp +++ b/modules/videoio/src/cap.cpp @@ -50,6 +50,17 @@ static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_V static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false); static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false); +#define CV_CAPTURE_LOG_DEBUG(tag, ...) \ + if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \ + { \ + CV_LOG_WARNING(nullptr, __VA_ARGS__); \ + } + +#define CV_WRITER_LOG_DEBUG(tag, ...) \ + if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \ + { \ + CV_LOG_WARNING(nullptr, __VA_ARGS__) \ + } void DefaultDeleter::operator ()(CvCapture* obj) const { cvReleaseCapture(&obj); } void DefaultDeleter::operator ()(CvVideoWriter* obj) const { cvReleaseVideoWriter(&obj); } @@ -80,7 +91,10 @@ bool VideoCapture::open(const String& filename, int apiPreference) { CV_TRACE_FUNCTION(); - if (isOpened()) release(); + if (isOpened()) + { + release(); + } const std::vector backends = cv::videoio_registry::getAvailableBackends_CaptureByFilename(); for (size_t i = 0; i < backends.size(); i++) @@ -88,8 +102,10 @@ bool VideoCapture::open(const String& filename, int apiPreference) const VideoBackendInfo& info = backends[i]; if (apiPreference == CAP_ANY || apiPreference == info.id) { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture filename='%s' ...", info.name, filename.c_str())); + + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): trying capture filename='%s' ...", + info.name, filename.c_str())); CV_Assert(!info.backendFactory.empty()); const Ptr backend = info.backendFactory->getBackend(); if (!backend.empty()) @@ -99,48 +115,79 @@ bool VideoCapture::open(const String& filename, int apiPreference) icap = backend->createCapture(filename); if (!icap.empty()) { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d", - info.name, icap->isOpened())); + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): created, isOpened=%d", + info.name, icap->isOpened())); if (icap->isOpened()) + { return true; + } icap.release(); } else { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name)); + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): can't create capture", + info.name)); + } + } + catch (const cv::Exception& e) + { + if (throwOnFail && apiPreference != CAP_ANY) + { + throw; } - } catch(const cv::Exception& e) { - if(throwOnFail && apiPreference != CAP_ANY) throw; - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what())); - } catch (const std::exception& e) { - if(throwOnFail && apiPreference != CAP_ANY) throw; - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what())); - } catch(...) { - if(throwOnFail && apiPreference != CAP_ANY) throw; - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name)); + CV_LOG_ERROR(NULL, + cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", + info.name, e.what())); + } + catch (const std::exception& e) + { + if (throwOnFail && apiPreference != CAP_ANY) + { + throw; + } + CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", + info.name, e.what())); + } + catch (...) + { + if (throwOnFail && apiPreference != CAP_ANY) + { + throw; + } + CV_LOG_ERROR(NULL, + cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", + info.name)); } } else { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \ - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name)); + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): backend is not available " + "(plugin is missing, or can't be loaded due " + "dependencies or it is not compatible)", + info.name)); } } } if (throwOnFail) + { CV_Error_(Error::StsError, ("could not open '%s'", filename.c_str())); + } return false; } -bool VideoCapture::open(int cameraNum, int apiPreference) +bool VideoCapture::open(int cameraNum, int apiPreference) { CV_TRACE_FUNCTION(); - if (isOpened()) release(); + if (isOpened()) + { + release(); + } if (apiPreference == CAP_ANY) { @@ -159,8 +206,10 @@ bool VideoCapture::open(int cameraNum, int apiPreference) const VideoBackendInfo& info = backends[i]; if (apiPreference == CAP_ANY || apiPreference == info.id) { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture cameraNum=%d ...", info.name, cameraNum)); + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): trying capture cameraNum=%d ...", + info.name, cameraNum)); + CV_Assert(!info.backendFactory.empty()); const Ptr backend = info.backendFactory->getBackend(); if (!backend.empty()) @@ -170,39 +219,67 @@ bool VideoCapture::open(int cameraNum, int apiPreference) icap = backend->createCapture(cameraNum); if (!icap.empty()) { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d", - info.name, icap->isOpened())); + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): created, isOpened=%d", + info.name, icap->isOpened())); if (icap->isOpened()) + { return true; + } icap.release(); } else { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name)); + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): can't create capture", + info.name)); + } + } + catch (const cv::Exception& e) + { + if (throwOnFail && apiPreference != CAP_ANY) + { + throw; + } + CV_LOG_ERROR(NULL, + cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", + info.name, e.what())); + } + catch (const std::exception& e) + { + if (throwOnFail && apiPreference != CAP_ANY) + { + throw; + } + CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", + info.name, e.what())); + } + catch (...) + { + if (throwOnFail && apiPreference != CAP_ANY) + { + throw; } - } catch(const cv::Exception& e) { - if(throwOnFail && apiPreference != CAP_ANY) throw; - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what())); - } catch (const std::exception& e) { - if(throwOnFail && apiPreference != CAP_ANY) throw; - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what())); - } catch(...) { - if(throwOnFail && apiPreference != CAP_ANY) throw; - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name)); + CV_LOG_ERROR(NULL, + cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", + info.name)); } } else { - if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \ - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name)); + CV_CAPTURE_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): backend is not available " + "(plugin is missing, or can't be loaded due " + "dependencies or it is not compatible)", + info.name)); } } } - if(throwOnFail) + if (throwOnFail) + { CV_Error_(Error::StsError, ("could not open camera %d", cameraNum)); + } return false; } @@ -216,9 +293,11 @@ String VideoCapture::getBackendName() const { int api = 0; if (icap) + { api = icap->isOpened() ? icap->getCaptureDomain() : 0; + } CV_Assert(api != 0); - return cv::videoio_registry::getBackendName((VideoCaptureAPIs)api); + return cv::videoio_registry::getBackendName(static_cast(api)); } void VideoCapture::release() @@ -232,7 +311,9 @@ bool VideoCapture::grab() CV_INSTRUMENT_REGION(); bool ret = !icap.empty() ? icap->grabFrame() : false; if (!ret && throwOnFail) + { CV_Error(Error::StsError, ""); + } return ret; } @@ -242,9 +323,13 @@ bool VideoCapture::retrieve(OutputArray image, int channel) bool ret = false; if (!icap.empty()) + { ret = icap->retrieveFrame(channel, image); + } if (!ret && throwOnFail) + { CV_Error_(Error::StsError, ("could not retrieve channel %d", channel)); + } return ret; } @@ -252,10 +337,12 @@ bool VideoCapture::read(OutputArray image) { CV_INSTRUMENT_REGION(); - if(grab()) + if (grab()) + { retrieve(image); - else + } else { image.release(); + } return !image.empty(); } @@ -300,7 +387,9 @@ bool VideoCapture::set(int propId, double value) CV_CheckNE(propId, (int)CAP_PROP_BACKEND, "Can't set read-only property"); bool ret = !icap.empty() ? icap->setProperty(propId, value) : false; if (!ret && throwOnFail) + { CV_Error_(Error::StsError, ("could not set prop %d = %f", propId, value)); + } return ret; } @@ -309,17 +398,22 @@ double VideoCapture::get(int propId) const if (propId == CAP_PROP_BACKEND) { int api = 0; - if (icap) - api = icap->isOpened() ? icap->getCaptureDomain() : 0; + if (icap && icap->isOpened()) + { + api = icap->getCaptureDomain(); + } if (api <= 0) + { return -1.0; - return (double)api; + } + return static_cast(api); } return !icap.empty() ? icap->getProperty(propId) : 0; } -bool VideoCapture::waitAny(const std::vector& streams, CV_OUT std::vector& readyIndex, int64 timeoutNs) +bool VideoCapture::waitAny(const std::vector& streams, + CV_OUT std::vector& readyIndex, int64 timeoutNs) { CV_Assert(!streams.empty()); @@ -331,17 +425,19 @@ bool VideoCapture::waitAny(const std::vector& streams, CV_OUT std: CV_CheckEQ((int)backend, (int)backend_i, "All captures must have the same backend"); } -#if (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO) // see cap_v4l.cpp guard +#if (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO) // see cap_v4l.cpp guard if (backend == CAP_V4L2) + { return VideoCapture_V4L_waitAny(streams, readyIndex, timeoutNs); + } #else - CV_UNUSED(readyIndex); CV_UNUSED(timeoutNs); + CV_UNUSED(readyIndex); + CV_UNUSED(timeoutNs); #endif CV_Error(Error::StsNotImplemented, "VideoCapture::waitAny() is supported by V4L backend only"); } - //================================================================================================= @@ -349,13 +445,15 @@ bool VideoCapture::waitAny(const std::vector& streams, CV_OUT std: VideoWriter::VideoWriter() {} -VideoWriter::VideoWriter(const String& filename, int _fourcc, double fps, Size frameSize, bool isColor) +VideoWriter::VideoWriter(const String& filename, int _fourcc, double fps, Size frameSize, + bool isColor) { open(filename, _fourcc, fps, frameSize, isColor); } -VideoWriter::VideoWriter(const String& filename, int apiPreference, int _fourcc, double fps, Size frameSize, bool isColor) +VideoWriter::VideoWriter(const String& filename, int apiPreference, int _fourcc, double fps, + Size frameSize, bool isColor) { open(filename, apiPreference, _fourcc, fps, frameSize, isColor); } @@ -370,16 +468,21 @@ VideoWriter::~VideoWriter() release(); } -bool VideoWriter::open(const String& filename, int _fourcc, double fps, Size frameSize, bool isColor) +bool VideoWriter::open(const String& filename, int _fourcc, double fps, Size frameSize, + bool isColor) { return open(filename, CAP_ANY, _fourcc, fps, frameSize, isColor); } -bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, double fps, Size frameSize, bool isColor) +bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, double fps, + Size frameSize, bool isColor) { CV_INSTRUMENT_REGION(); - if (isOpened()) release(); + if (isOpened()) + { + release(); + } const std::vector backends = cv::videoio_registry::getAvailableBackends_Writer(); for (size_t i = 0; i < backends.size(); i++) @@ -387,9 +490,11 @@ bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, d const VideoBackendInfo& info = backends[i]; if (apiPreference == CAP_ANY || apiPreference == info.id) { - if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying writer with filename='%s' fourcc=0x%08x fps=%g sz=%dx%d isColor=%d...", - info.name, filename.c_str(), (unsigned)_fourcc, fps, frameSize.width, frameSize.height, (int)isColor)); + CV_WRITER_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): trying writer with filename='%s' " + "fourcc=0x%08x fps=%g sz=%dx%d isColor=%d...", + info.name, filename.c_str(), (unsigned)_fourcc, fps, + frameSize.width, frameSize.height, (int)isColor)); CV_Assert(!info.backendFactory.empty()); const Ptr backend = info.backendFactory->getBackend(); if (!backend.empty()) @@ -399,30 +504,47 @@ bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, d iwriter = backend->createWriter(filename, _fourcc, fps, frameSize, isColor); if (!iwriter.empty()) { - if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d", - info.name, iwriter->isOpened())); + + CV_WRITER_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): created, isOpened=%d", + info.name, iwriter->isOpened())); if (iwriter->isOpened()) + { return true; + } iwriter.release(); } else { - if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create writer", info.name)); + CV_WRITER_LOG_DEBUG(NULL, cv::format("VIDEOIO(%s): can't create writer", + info.name)); } - } catch(const cv::Exception& e) { - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what())); - } catch (const std::exception& e) { - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what())); - } catch(...) { - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name)); + } + catch (const cv::Exception& e) + { + CV_LOG_ERROR(NULL, + cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", + info.name, e.what())); + } + catch (const std::exception& e) + { + CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", + info.name, e.what())); + } + catch (...) + { + CV_LOG_ERROR(NULL, + cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", + info.name)); } } else { - if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \ - CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name)); + CV_WRITER_LOG_DEBUG(NULL, + cv::format("VIDEOIO(%s): backend is not available " + "(plugin is missing, or can't be loaded due " + "dependencies or it is not compatible)", + info.name)); } } } @@ -440,7 +562,9 @@ bool VideoWriter::set(int propId, double value) CV_CheckNE(propId, (int)CAP_PROP_BACKEND, "Can't set read-only property"); if (!iwriter.empty()) + { return iwriter->setProperty(propId, value); + } return false; } @@ -450,13 +574,15 @@ double VideoWriter::get(int propId) const { int api = 0; if (iwriter) + { api = iwriter->getCaptureDomain(); - if (api <= 0) - return -1.0; - return (double)api; + } + return (api <= 0) ? -1. : static_cast(api); } if (!iwriter.empty()) + { return iwriter->getProperty(propId); + } return 0.; } @@ -464,17 +590,21 @@ String VideoWriter::getBackendName() const { int api = 0; if (iwriter) + { api = iwriter->getCaptureDomain(); + } CV_Assert(api != 0); - return cv::videoio_registry::getBackendName((VideoCaptureAPIs)api); + return cv::videoio_registry::getBackendName(static_cast(api)); } void VideoWriter::write(InputArray image) { CV_INSTRUMENT_REGION(); - if( iwriter ) + if (iwriter) + { iwriter->write(image); + } } VideoWriter& VideoWriter::operator << (const Mat& image) @@ -498,4 +628,4 @@ int VideoWriter::fourcc(char c1, char c2, char c3, char c4) return (c1 & 255) + ((c2 & 255) << 8) + ((c3 & 255) << 16) + ((c4 & 255) << 24); } -} // namespace +} // namespace cv