Skip to content

Commit

Permalink
Merge pull request opencv#19394 from MaximMilashchenko:params
Browse files Browse the repository at this point in the history
add video capture parameters

* add parameters

* videoio: revert unnecessary massive changes

* videoio: support capture parameters in backends API

- add tests
- FFmpeg backend sample code
- StaticBackend API is done
- support through PluginBackend API will be added later

Co-authored-by: Milashchenko <[email protected]>
Co-authored-by: Alexander Alekhin <[email protected]>
  • Loading branch information
3 people authored Jan 27, 2021
1 parent 37c12db commit 4678704
Show file tree
Hide file tree
Showing 10 changed files with 427 additions and 29 deletions.
42 changes: 42 additions & 0 deletions modules/videoio/include/opencv2/videoio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,14 @@ class CV_EXPORTS_W VideoCapture
*/
CV_WRAP explicit VideoCapture(const String& filename, int apiPreference = CAP_ANY);

/** @overload
@brief Opens a video file or a capturing device or an IP video stream for video capturing with API Preference and parameters
The `params` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`.
See cv::VideoCaptureProperties
*/
CV_WRAP explicit VideoCapture(const String& filename, int apiPreference, const std::vector<int>& params);

/** @overload
@brief Opens a camera for video capturing
Expand All @@ -663,6 +671,14 @@ class CV_EXPORTS_W VideoCapture
*/
CV_WRAP explicit VideoCapture(int index, int apiPreference = CAP_ANY);

/** @overload
@brief Opens a camera for video capturing with API Preference and parameters
The `params` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`.
See cv::VideoCaptureProperties
*/
CV_WRAP explicit VideoCapture(int index, int apiPreference, const std::vector<int>& params);

/** @brief Default destructor
The method first calls VideoCapture::release to close the already opened file or camera.
Expand All @@ -684,6 +700,19 @@ class CV_EXPORTS_W VideoCapture
@overload
The `params` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`.
See cv::VideoCaptureProperties
@return `true` if the file has been successfully opened
The method first calls VideoCapture::release to close the already opened file or camera.
*/
CV_WRAP virtual bool open(const String& filename, int apiPreference, const std::vector<int>& params);

/** @brief Opens a camera for video capturing
@overload
Parameters are same as the constructor VideoCapture(int index, int apiPreference = CAP_ANY)
@return `true` if the camera has been successfully opened.
Expand All @@ -693,6 +722,19 @@ class CV_EXPORTS_W VideoCapture

/** @brief Returns true if video capturing has been initialized already.
@overload
The `params` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`.
See cv::VideoCaptureProperties
@return `true` if the camera has been successfully opened.
The method first calls VideoCapture::release to close the already opened file or camera.
*/
CV_WRAP virtual bool open(int index, int apiPreference, const std::vector<int>& params);

/** @brief Returns true if video capturing has been initialized already.
If the previous call to VideoCapture constructor or VideoCapture::open() succeeded, the method returns
true.
*/
Expand Down
3 changes: 2 additions & 1 deletion modules/videoio/misc/objc/gen_dict.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
},
"func_arg_fix" : {
"VideoCapture" : {
"(BOOL)open:(int)index apiPreference:(int)apiPreference" : { "open" : {"name" : "openWithIndex"} }
"(BOOL)open:(int)index apiPreference:(int)apiPreference" : { "open" : {"name" : "openWithIndex"} },
"(BOOL)open:(int)index apiPreference:(int)apiPreference params:(IntVector*)params" : { "open" : {"name" : "openWithIndexAndParameters"} }
}
}
}
11 changes: 9 additions & 2 deletions modules/videoio/src/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class IBackend
{
public:
virtual ~IBackend() {}
virtual Ptr<IVideoCapture> createCapture(int camera) const = 0;
virtual Ptr<IVideoCapture> createCapture(const std::string &filename) const = 0;
virtual Ptr<IVideoCapture> createCapture(int camera, const VideoCaptureParameters& params) const = 0;
virtual Ptr<IVideoCapture> createCapture(const std::string &filename, const VideoCaptureParameters& params) const = 0;
virtual Ptr<IVideoWriter> createWriter(const std::string& filename, int fourcc, double fps, const cv::Size& sz,
const VideoWriterParameters& params) const = 0;
};
Expand All @@ -33,14 +33,21 @@ class IBackendFactory

typedef Ptr<IVideoCapture> (*FN_createCaptureFile)(const std::string & filename);
typedef Ptr<IVideoCapture> (*FN_createCaptureCamera)(int camera);
typedef Ptr<IVideoCapture> (*FN_createCaptureFileWithParams)(const std::string & filename, const VideoCaptureParameters& params);
typedef Ptr<IVideoCapture> (*FN_createCaptureCameraWithParams)(int camera, const VideoCaptureParameters& params);
typedef Ptr<IVideoWriter> (*FN_createWriter)(const std::string& filename, int fourcc, double fps, const Size& sz,
const VideoWriterParameters& params);
Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFile createCaptureFile,
FN_createCaptureCamera createCaptureCamera,
FN_createWriter createWriter);
Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFileWithParams createCaptureFile,
FN_createCaptureCameraWithParams createCaptureCamera,
FN_createWriter createWriter);

Ptr<IBackendFactory> createPluginBackendFactory(VideoCaptureAPIs id, const char* baseName);

void applyParametersFallback(const Ptr<IVideoCapture>& cap, const VideoCaptureParameters& params);

} // namespace cv::

#endif // BACKEND_HPP_DEFINED
30 changes: 28 additions & 2 deletions modules/videoio/src/backend_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,10 @@ class PluginBackend: public IBackend
}
}

Ptr<IVideoCapture> createCapture(int camera) const CV_OVERRIDE;
Ptr<IVideoCapture> createCapture(const std::string &filename) const CV_OVERRIDE;
Ptr<IVideoCapture> createCapture(int camera) const;
Ptr<IVideoCapture> createCapture(int camera, const VideoCaptureParameters& params) const CV_OVERRIDE;
Ptr<IVideoCapture> createCapture(const std::string &filename) const;
Ptr<IVideoCapture> createCapture(const std::string &filename, const VideoCaptureParameters& params) const CV_OVERRIDE;
Ptr<IVideoWriter> createWriter(const std::string& filename, int fourcc, double fps,
const cv::Size& sz, const VideoWriterParameters& params) const CV_OVERRIDE;
};
Expand Down Expand Up @@ -753,10 +755,22 @@ Ptr<IVideoCapture> PluginBackend::createCapture(int camera) const
catch (...)
{
CV_LOG_DEBUG(NULL, "Video I/O: can't create camera capture: " << camera);
throw;
}
return Ptr<IVideoCapture>();
}

Ptr<IVideoCapture> PluginBackend::createCapture(int camera, const VideoCaptureParameters& params) const
{
// TODO Update plugins API to support parameters
Ptr<IVideoCapture> cap = createCapture(camera);
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}

Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename) const
{
try
Expand All @@ -769,10 +783,22 @@ Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename) con
catch (...)
{
CV_LOG_DEBUG(NULL, "Video I/O: can't open file capture: " << filename);
throw;
}
return Ptr<IVideoCapture>();
}

Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename, const VideoCaptureParameters& params) const
{
// TODO Update plugins API to support parameters
Ptr<IVideoCapture> cap = createCapture(filename);
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}

Ptr<IVideoWriter> PluginBackend::createWriter(const std::string& filename, int fourcc, double fps,
const cv::Size& sz, const VideoWriterParameters& params) const
{
Expand Down
113 changes: 109 additions & 4 deletions modules/videoio/src/backend_static.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,28 @@

namespace cv {


void applyParametersFallback(const Ptr<IVideoCapture>& cap, const VideoCaptureParameters& params)
{
std::vector<int> props = params.getUnused();
CV_LOG_INFO(NULL, "VIDEOIO: Backend '" << videoio_registry::getBackendName((VideoCaptureAPIs)cap->getCaptureDomain()) <<
"' implementation doesn't support parameters in .open(). Applying " <<
props.size() << " properties through .setProperty()");
for (int prop : props)
{
double value = params.get<double>(prop, -1);
CV_LOG_INFO(NULL, "VIDEOIO: apply parameter: [" << prop << "]=" <<
cv::format("%g / %lld / 0x%16llx", value, (long long)value, (long long)value));
if (!cap->setProperty(prop, value))
{
CV_Error_(cv::Error::StsNotImplemented, ("VIDEOIO: Failed to apply invalid or unsupported parameter: [%d]=%g / %lld / 0x%08llx", prop, value, (long long)value, (long long)value));
}
}
// NB: there is no dedicated "commit" parameters event, implementations should commit after each property automatically
}


// Legacy API. Modern API with parameters is below
class StaticBackend: public IBackend
{
public:
Expand All @@ -20,18 +42,33 @@ class StaticBackend: public IBackend
{
// nothing
}

~StaticBackend() CV_OVERRIDE {}

Ptr<IVideoCapture> createCapture(int camera) const CV_OVERRIDE
Ptr<IVideoCapture> createCapture(int camera, const VideoCaptureParameters& params) const CV_OVERRIDE
{
if (fn_createCaptureCamera_)
return fn_createCaptureCamera_(camera);
{
Ptr<IVideoCapture> cap = fn_createCaptureCamera_(camera);
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}
return Ptr<IVideoCapture>();
}
Ptr<IVideoCapture> createCapture(const std::string &filename) const CV_OVERRIDE
Ptr<IVideoCapture> createCapture(const std::string &filename, const VideoCaptureParameters& params) const CV_OVERRIDE
{
if (fn_createCaptureFile_)
return fn_createCaptureFile_(filename);
{
Ptr<IVideoCapture> cap = fn_createCaptureFile_(filename);
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}
return Ptr<IVideoCapture>();
}
Ptr<IVideoWriter> createWriter(const std::string& filename, int fourcc, double fps,
Expand Down Expand Up @@ -63,11 +100,79 @@ class StaticBackendFactory : public IBackendFactory
}
};


Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFile createCaptureFile,
FN_createCaptureCamera createCaptureCamera,
FN_createWriter createWriter)
{
return makePtr<StaticBackendFactory>(createCaptureFile, createCaptureCamera, createWriter).staticCast<IBackendFactory>();
}



class StaticBackendWithParams: public IBackend
{
public:
FN_createCaptureFileWithParams fn_createCaptureFile_;
FN_createCaptureCameraWithParams fn_createCaptureCamera_;
FN_createWriter fn_createWriter_;

StaticBackendWithParams(FN_createCaptureFileWithParams fn_createCaptureFile, FN_createCaptureCameraWithParams fn_createCaptureCamera, FN_createWriter fn_createWriter)
: fn_createCaptureFile_(fn_createCaptureFile), fn_createCaptureCamera_(fn_createCaptureCamera), fn_createWriter_(fn_createWriter)
{
// nothing
}

~StaticBackendWithParams() CV_OVERRIDE {}

Ptr<IVideoCapture> createCapture(int camera, const VideoCaptureParameters& params) const CV_OVERRIDE
{
if (fn_createCaptureCamera_)
return fn_createCaptureCamera_(camera, params);
return Ptr<IVideoCapture>();
}
Ptr<IVideoCapture> createCapture(const std::string &filename, const VideoCaptureParameters& params) const CV_OVERRIDE
{
if (fn_createCaptureFile_)
return fn_createCaptureFile_(filename, params);
return Ptr<IVideoCapture>();
}
Ptr<IVideoWriter> createWriter(const std::string& filename, int fourcc, double fps,
const cv::Size& sz, const VideoWriterParameters& params) const CV_OVERRIDE
{
if (fn_createWriter_)
return fn_createWriter_(filename, fourcc, fps, sz, params);
return Ptr<IVideoWriter>();
}
}; // StaticBackendWithParams

class StaticBackendWithParamsFactory : public IBackendFactory
{
protected:
Ptr<StaticBackendWithParams> backend;

public:
StaticBackendWithParamsFactory(FN_createCaptureFileWithParams createCaptureFile, FN_createCaptureCameraWithParams createCaptureCamera, FN_createWriter createWriter)
: backend(makePtr<StaticBackendWithParams>(createCaptureFile, createCaptureCamera, createWriter))
{
// nothing
}

~StaticBackendWithParamsFactory() CV_OVERRIDE {}

Ptr<IBackend> getBackend() const CV_OVERRIDE
{
return backend.staticCast<IBackend>();
}
};


Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFileWithParams createCaptureFile,
FN_createCaptureCameraWithParams createCaptureCamera,
FN_createWriter createWriter)
{
return makePtr<StaticBackendWithParamsFactory>(createCaptureFile, createCaptureCamera, createWriter).staticCast<IBackendFactory>();
}


} // namespace
Loading

0 comments on commit 4678704

Please sign in to comment.