VideoIO classes refactoring

- Added `explicit` to `VideoCapture` constructors with 2
    arguments, 1 of them has default value
  - Applied library code style
  - Introduced 2 debug macros to improve readability of the code
This commit is contained in:
Vadim Levin 2019-12-27 12:42:09 +03:00
parent 89d3f95a8e
commit 3fe9dfaa2e
2 changed files with 209 additions and 79 deletions

View File

@ -628,7 +628,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
@ -640,7 +640,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

View File

@ -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<CvCapture>::operator ()(CvCapture* obj) const { cvReleaseCapture(&obj); }
void DefaultDeleter<CvVideoWriter>::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<VideoBackendInfo> 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<IBackend> 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;
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));
}
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));
}
}
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<IBackend> 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;
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", 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;
}
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<VideoCaptureAPIs>(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<double>(api);
}
return !icap.empty() ? icap->getProperty(propId) : 0;
}
bool VideoCapture::waitAny(const std::vector<VideoCapture>& streams, CV_OUT std::vector<int>& readyIndex, int64 timeoutNs)
bool VideoCapture::waitAny(const std::vector<VideoCapture>& streams,
CV_OUT std::vector<int>& readyIndex, int64 timeoutNs)
{
CV_Assert(!streams.empty());
@ -331,17 +425,19 @@ bool VideoCapture::waitAny(const std::vector<VideoCapture>& 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<VideoCapture>& 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<VideoBackendInfo> 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<IBackend> 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<double>(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<VideoCaptureAPIs>(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