public:
static
Ptr<PluginCapture> create(const OpenCV_VideoIO_Capture_Plugin_API* plugin_api,
- const std::string &filename, int camera)
+ const std::string &filename, int camera, const VideoCaptureParameters& params)
{
CV_Assert(plugin_api);
+ CV_Assert(plugin_api->v0.Capture_release);
+
CvPluginCapture capture = NULL;
- if (plugin_api->v0.Capture_open)
+ if (plugin_api->api_header.api_version >= 1 && plugin_api->v1.Capture_open_with_params)
{
- CV_Assert(plugin_api->v0.Capture_release);
- if (CV_ERROR_OK == plugin_api->v0.Capture_open(filename.empty() ? 0 : filename.c_str(), camera, &capture))
+ std::vector<int> vint_params = params.getIntVector();
+ int* c_params = &vint_params[0];
+ unsigned n_params = (unsigned)(vint_params.size() / 2);
+
+ if (CV_ERROR_OK == plugin_api->v1.Capture_open_with_params(
+ filename.empty() ? 0 : filename.c_str(), camera, c_params, n_params, &capture))
{
CV_Assert(capture);
return makePtr<PluginCapture>(plugin_api, capture);
}
}
+ else if (plugin_api->v0.Capture_open)
+ {
+ if (CV_ERROR_OK == plugin_api->v0.Capture_open(filename.empty() ? 0 : filename.c_str(), camera, &capture))
+ {
+ CV_Assert(capture);
+ Ptr<PluginCapture> cap = makePtr<PluginCapture>(plugin_api, capture);
+ if (cap && !params.empty())
+ {
+ applyParametersFallback(cap, params);
+ }
+ return cap;
+ }
+ }
+
return Ptr<PluginCapture>();
}
const VideoWriterParameters& params)
{
CV_Assert(plugin_api);
+ CV_Assert(plugin_api->v0.Writer_release);
+ CV_Assert(!filename.empty());
+
CvPluginWriter writer = NULL;
+
if (plugin_api->api_header.api_version >= 1 && plugin_api->v1.Writer_open_with_params)
{
- CV_Assert(plugin_api->v0.Writer_release);
- CV_Assert(!filename.empty());
std::vector<int> vint_params = params.getIntVector();
int* c_params = &vint_params[0];
unsigned n_params = (unsigned)(vint_params.size() / 2);
}
else if (plugin_api->v0.Writer_open)
{
- CV_Assert(plugin_api->v0.Writer_release);
- CV_Assert(!filename.empty());
const bool isColor = params.get(VIDEOWRITER_PROP_IS_COLOR, true);
const int depth = params.get(VIDEOWRITER_PROP_DEPTH, CV_8U);
if (depth != CV_8U)
CV_LOG_WARNING(NULL, "Video I/O plugin doesn't support (due to lower API level) creation of VideoWriter with depth != CV_8U");
return Ptr<PluginWriter>();
}
+ if (params.warnUnusedParameters())
+ {
+ CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in VideoWriter, see logger INFO channel for details");
+ return Ptr<PluginWriter>();
+ }
if (CV_ERROR_OK == plugin_api->v0.Writer_open(filename.c_str(), fourcc, fps, sz.width, sz.height, isColor, &writer))
{
CV_Assert(writer);
return makePtr<PluginWriter>(plugin_api, writer);
}
}
+
return Ptr<PluginWriter>();
}
};
-Ptr<IVideoCapture> PluginBackend::createCapture(int camera) const
+Ptr<IVideoCapture> PluginBackend::createCapture(int camera, const VideoCaptureParameters& params) const
{
try
{
if (capture_api_)
- return PluginCapture::create(capture_api_, std::string(), camera); //.staticCast<IVideoCapture>();
+ return PluginCapture::create(capture_api_, std::string(), camera, params); //.staticCast<IVideoCapture>();
if (plugin_api_)
- return legacy::PluginCapture::create(plugin_api_, std::string(), camera); //.staticCast<IVideoCapture>();
+ {
+ Ptr<IVideoCapture> cap = legacy::PluginCapture::create(plugin_api_, std::string(), camera); //.staticCast<IVideoCapture>();
+ if (cap && !params.empty())
+ {
+ applyParametersFallback(cap, params);
+ }
+ return cap;
+ }
}
catch (...)
{
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
+Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename, const VideoCaptureParameters& params) const
{
try
{
if (capture_api_)
- return PluginCapture::create(capture_api_, filename, 0); //.staticCast<IVideoCapture>();
+ return PluginCapture::create(capture_api_, filename, 0, params); //.staticCast<IVideoCapture>();
if (plugin_api_)
- return legacy::PluginCapture::create(plugin_api_, filename, 0); //.staticCast<IVideoCapture>();
+ {
+ Ptr<IVideoCapture> cap = legacy::PluginCapture::create(plugin_api_, filename, 0); //.staticCast<IVideoCapture>();
+ if (cap && !params.empty())
+ {
+ applyParametersFallback(cap, params);
+ }
+ return cap;
+ }
}
catch (...)
{
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
{
}
VideoCapture::VideoCapture(const String& filename, int apiPreference, const std::vector<int>& params)
- : throwOnFail(true)
+ : throwOnFail(false)
{
CV_TRACE_FUNCTION();
open(filename, apiPreference, params);
}
VideoCapture::VideoCapture(int index, int apiPreference, const std::vector<int>& params)
- : throwOnFail(true)
+ : throwOnFail(false)
{
CV_TRACE_FUNCTION();
open(index, apiPreference, params);
#include "cap_ffmpeg_impl.hpp"
-#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
+// TODO drop legacy code
+//#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
#define icvReleaseCapture_FFMPEG_p cvReleaseCapture_FFMPEG
#define icvGrabFrame_FFMPEG_p cvGrabFrame_FFMPEG
#define icvRetrieveFrame_FFMPEG_p cvRetrieveFrame_FFMPEG
return true;
}
- virtual bool open( const cv::String& filename )
- {
- close();
-
- ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename.c_str() );
- return ffmpegCapture != 0;
- }
bool open(const cv::String& filename, const cv::VideoCaptureParameters& params)
{
close();
- ffmpegCapture = icvCreateFileCapture_FFMPEG_p(filename.c_str());
- if (ffmpegCapture && !params.empty())
- {
- if (params.has(CAP_PROP_FORMAT)) // just a sample code
- {
- int value = params.get<int>(CAP_PROP_FORMAT);
- if (!setProperty(CAP_PROP_FORMAT, value))
- {
- CV_Error_(Error::StsBadArg, ("VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: %d", value));
- }
- }
- if (params.warnUnusedParameters())
- {
- CV_Error(Error::StsBadArg, "VIDEOIO/FFMPEG: unsupported parameters in .open(), see logger INFO channel for details");
- }
- }
+ ffmpegCapture = cvCreateFileCaptureWithParams_FFMPEG(filename.c_str(), params);
return ffmpegCapture != 0;
}
- virtual void close()
+ void close()
{
if (ffmpegCapture)
icvReleaseCapture_FFMPEG_p( &ffmpegCapture );
#include "plugin_api.hpp"
#else
#define CAPTURE_ABI_VERSION 1
-#define CAPTURE_API_VERSION 0
+#define CAPTURE_API_VERSION 1
#include "plugin_capture_api.hpp"
#define WRITER_ABI_VERSION 1
#define WRITER_API_VERSION 0
}
static
+CvResult CV_API_CALL cv_capture_open_with_params(
+ const char* filename, int camera_index,
+ int* params, unsigned n_params,
+ CV_OUT CvPluginCapture* handle
+)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ *handle = NULL;
+ if (!filename)
+ return CV_ERROR_FAIL;
+ CV_UNUSED(camera_index);
+ CvCapture_FFMPEG_proxy *cap = 0;
+ try
+ {
+ cv::VideoCaptureParameters parameters(params, n_params);
+ cap = new CvCapture_FFMPEG_proxy(filename, parameters);
+ if (cap->isOpened())
+ {
+ *handle = (CvPluginCapture)cap;
+ return CV_ERROR_OK;
+ }
+ }
+ catch (...)
+ {
+ }
+ if (cap)
+ delete cap;
+ return CV_ERROR_FAIL;
+}
+
+static
CvResult CV_API_CALL cv_capture_release(CvPluginCapture handle)
{
if (!handle)
/* 5*/cv_capture_set_prop,
/* 6*/cv_capture_grab,
/* 7*/cv_capture_retrieve,
+ },
+ {
+ /* 8*/cv_capture_open_with_params,
}
};
struct CvCapture_FFMPEG
{
- bool open( const char* filename );
+ bool open(const char* filename, const VideoCaptureParameters& params);
void close();
double getProperty(int) const;
}
};
-bool CvCapture_FFMPEG::open( const char* _filename )
+bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& params)
{
InternalFFMpegRegister::init();
AutoLock lock(_mutex);
close();
+ if (!params.empty())
+ {
+ if (params.has(CAP_PROP_FORMAT))
+ {
+ int value = params.get<int>(CAP_PROP_FORMAT);
+ if (value == -1)
+ {
+ CV_LOG_INFO(NULL, "VIDEOIO/FFMPEG: enabled demuxer only mode: '" << (_filename ? _filename : "<NULL>") << "'");
+ rawMode = true;
+ }
+ else
+ {
+ CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: " << value);
+ return false;
+ }
+ }
+ if (params.warnUnusedParameters())
+ {
+ CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in .open(), see logger INFO channel for details");
+ return false;
+ }
+ }
+
#if USE_AV_INTERRUPT_CALLBACK
/* interrupt callback */
interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;
-CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
+static
+CvCapture_FFMPEG* cvCreateFileCaptureWithParams_FFMPEG(const char* filename, const VideoCaptureParameters& params)
{
+ // FIXIT: remove unsafe malloc() approach
CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));
if (!capture)
return 0;
capture->init();
- if( capture->open( filename ))
+ if (capture->open(filename, params))
return capture;
capture->close();
return 0;
}
-
void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)
{
if( capture && *capture )
typedef struct CvCapture_FFMPEG CvCapture_FFMPEG;
typedef struct CvVideoWriter_FFMPEG CvVideoWriter_FFMPEG;
-OPENCV_FFMPEG_API struct CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG(const char* filename);
+//OPENCV_FFMPEG_API struct CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG(const char* filename);
OPENCV_FFMPEG_API int cvSetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap,
int prop, double value);
OPENCV_FFMPEG_API double cvGetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap, int prop);
}
}
+ VideoParameters(int* params, unsigned n_params)
+ {
+ params_.reserve(n_params);
+ for (unsigned i = 0; i < n_params; ++i)
+ {
+ add(params[2*i], params[2*i + 1]);
+ }
+ }
+
void add(int key, int value)
{
params_.emplace_back(key, value);
class VideoWriterParameters : public VideoParameters
{
public:
- VideoWriterParameters() = default;
-
- explicit VideoWriterParameters(const std::vector<int>& params) : VideoParameters(params) {};
+ using VideoParameters::VideoParameters; // reuse constructors
};
class VideoCaptureParameters : public VideoParameters
{
public:
- VideoCaptureParameters() = default;
-
- explicit VideoCaptureParameters(const std::vector<int>& params) : VideoParameters(params) {};
+ using VideoParameters::VideoParameters; // reuse constructors
};
class IVideoCapture
/// increased for backward-compatible changes, e.g. add new function
/// Caller API <= Plugin API -> plugin is fully compatible
/// Caller API > Plugin API -> plugin is not fully compatible, caller should use extra checks to use plugins with older API
-#define CAPTURE_API_VERSION 0
+#define CAPTURE_API_VERSION 1
/// increased for incompatible changes, e.g. remove function argument
/// Caller ABI == Plugin ABI -> plugin is compatible
CvResult (CV_API_CALL *Capture_retreive)(CvPluginCapture handle, int stream_idx, cv_videoio_capture_retrieve_cb_t callback, void* userdata);
}; // OpenCV_VideoIO_Capture_Plugin_API_v1_0_api_entries
-#if 0
struct OpenCV_VideoIO_Capture_Plugin_API_v1_1_api_entries
{
- /** @brief TBD
+ /** @brief Open video capture with parameters
- @note API-CALL XXX, API-Version == YYY
+ @param filename File name or NULL to use camera_index instead
+ @param camera_index Camera index (used if filename == NULL)
+ @param params pointer on 2*n_params array of 'key,value' pairs
+ @param n_params number of passed parameters
+ @param[out] handle pointer on Capture handle
+
+ @note API-CALL 8, API-Version == 1
*/
- CvResult (CV_API_CALL* zzz)(
- ...
- );
+ CvResult (CV_API_CALL *Capture_open_with_params)(
+ const char* filename, int camera_index,
+ int* params, unsigned n_params,
+ CV_OUT CvPluginCapture* handle);
}; // OpenCV_VideoIO_Capture_Plugin_API_v1_1_api_entries
-#endif
typedef struct OpenCV_VideoIO_Capture_Plugin_API_v1_0
{
struct OpenCV_VideoIO_Capture_Plugin_API_v1_0_api_entries v0;
} OpenCV_VideoIO_Capture_Plugin_API_v1_0;
-#if 0
typedef struct OpenCV_VideoIO_Capture_Plugin_API_v1_1
{
OpenCV_API_Header api_header;
struct OpenCV_VideoIO_Capture_Plugin_API_v1_0_api_entries v0;
struct OpenCV_VideoIO_Capture_Plugin_API_v1_1_api_entries v1;
} OpenCV_VideoIO_Capture_Plugin_API_v1_1;
-#endif
-#if 0 //CAPTURE_ABI_VERSION == 1 && CAPTURE_API_VERSION == 1
+#if CAPTURE_ABI_VERSION == 1 && CAPTURE_API_VERSION == 1
typedef struct OpenCV_VideoIO_Capture_Plugin_API_v1_1 OpenCV_VideoIO_Capture_Plugin_API;
#elif CAPTURE_ABI_VERSION == 1 && CAPTURE_API_VERSION == 0
typedef struct OpenCV_VideoIO_Capture_Plugin_API_v1_0 OpenCV_VideoIO_Capture_Plugin_API;
throw SkipTestException("FFmpeg backend was not found");
string video_file = findDataFile("video/big_buck_bunny.mp4");
- EXPECT_ANY_THROW(
- {
- VideoCapture cap(video_file, CAP_FFMPEG, {
- CAP_PROP_FORMAT, -2 // invalid
- });
+ VideoCapture cap(video_file, CAP_FFMPEG, {
+ CAP_PROP_FORMAT, -2 // invalid
});
+ EXPECT_FALSE(cap.isOpened());
}