diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index c1c67543f6..4659f750e6 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -91,9 +91,13 @@ if(TARGET ocv.3rdparty.dshow) endif() if(TARGET ocv.3rdparty.msmf) - list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_msmf.hpp) - list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_msmf.cpp) - list(APPEND tgts ocv.3rdparty.msmf) + if("msmf" IN_LIST VIDEOIO_PLUGIN_LIST) + ocv_create_builtin_videoio_plugin("opencv_videoio_msmf" ocv.3rdparty.msmf "cap_msmf.cpp") + else() + list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_msmf.hpp) + list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_msmf.cpp) + list(APPEND tgts ocv.3rdparty.msmf) + endif() endif() if(TARGET ocv.3rdparty.xine) diff --git a/modules/videoio/src/cap_mfx_plugin.cpp b/modules/videoio/src/cap_mfx_plugin.cpp index 098f4d7d12..f4e63014ec 100644 --- a/modules/videoio/src/cap_mfx_plugin.cpp +++ b/modules/videoio/src/cap_mfx_plugin.cpp @@ -114,7 +114,7 @@ CvResult CV_API_CALL cv_capture_retrieve(CvPluginCapture handle, int stream_idx, VideoCapture_IntelMFX* instance = (VideoCapture_IntelMFX*)handle; Mat img; if (instance->retrieveFrame(stream_idx, img)) - return callback(stream_idx, img.data, img.step, img.cols, img.rows, img.channels(), userdata); + return callback(stream_idx, img.data, (int)img.step, img.cols, img.rows, img.channels(), userdata); return CV_ERROR_FAIL; } catch(...) diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index f1637ba670..1a0f2e093b 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -3,7 +3,6 @@ // of this distribution and at http://opencv.org/license.html #include "precomp.hpp" -#if defined _WIN32 && defined HAVE_MSMF /* Media Foundation-based Video Capturing module is based on videoInput library by Evgeny Pereguda: @@ -1669,4 +1668,221 @@ cv::Ptr cv::cvCreateVideoWriter_MSMF( const std::string& filen return cv::Ptr(); } -#endif +#if defined(BUILD_PLUGIN) + +#include "plugin_api.hpp" + +namespace cv { + +typedef CvCapture_MSMF CaptureT; +typedef CvVideoWriter_MSMF WriterT; + +static +CvResult CV_API_CALL cv_capture_open(const char* filename, int camera_index, CV_OUT CvPluginCapture* handle) +{ + if (!handle) + return CV_ERROR_FAIL; + *handle = NULL; + if (!filename) + return CV_ERROR_FAIL; + CaptureT* cap = 0; + try + { + cap = new CaptureT(); + bool res; + if (filename) + res = cap->open(std::string(filename)); + else + res = cap->open(camera_index); + if (res) + { + *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) + return CV_ERROR_FAIL; + CaptureT* instance = (CaptureT*)handle; + delete instance; + return CV_ERROR_OK; +} + + +static +CvResult CV_API_CALL cv_capture_get_prop(CvPluginCapture handle, int prop, CV_OUT double* val) +{ + if (!handle) + return CV_ERROR_FAIL; + if (!val) + return CV_ERROR_FAIL; + try + { + CaptureT* instance = (CaptureT*)handle; + *val = instance->getProperty(prop); + return CV_ERROR_OK; + } + catch (...) + { + return CV_ERROR_FAIL; + } +} + +static +CvResult CV_API_CALL cv_capture_set_prop(CvPluginCapture handle, int prop, double val) +{ + if (!handle) + return CV_ERROR_FAIL; + try + { + CaptureT* instance = (CaptureT*)handle; + return instance->setProperty(prop, val) ? CV_ERROR_OK : CV_ERROR_FAIL; + } + catch (...) + { + return CV_ERROR_FAIL; + } +} + +static +CvResult CV_API_CALL cv_capture_grab(CvPluginCapture handle) +{ + if (!handle) + return CV_ERROR_FAIL; + try + { + CaptureT* instance = (CaptureT*)handle; + return instance->grabFrame() ? CV_ERROR_OK : CV_ERROR_FAIL; + } + catch (...) + { + return CV_ERROR_FAIL; + } +} + +static +CvResult CV_API_CALL cv_capture_retrieve(CvPluginCapture handle, int stream_idx, cv_videoio_retrieve_cb_t callback, void* userdata) +{ + if (!handle) + return CV_ERROR_FAIL; + try + { + CaptureT* instance = (CaptureT*)handle; + Mat img; + if (instance->retrieveFrame(stream_idx, img)) + return callback(stream_idx, img.data, (int)img.step, img.cols, img.rows, img.channels(), userdata); + return CV_ERROR_FAIL; + } + catch (...) + { + return CV_ERROR_FAIL; + } +} + +static +CvResult CV_API_CALL cv_writer_open(const char* filename, int fourcc, double fps, int width, int height, int isColor, CV_OUT CvPluginWriter* handle) +{ + WriterT* wrt = 0; + try + { + wrt = new WriterT(); + Size sz(width, height); + if (wrt && wrt->open(filename, fourcc, fps, sz, isColor)) + { + *handle = (CvPluginWriter)wrt; + return CV_ERROR_OK; + } + } + catch (...) + { + } + if (wrt) + delete wrt; + return CV_ERROR_FAIL; +} + +static +CvResult CV_API_CALL cv_writer_release(CvPluginWriter handle) +{ + if (!handle) + return CV_ERROR_FAIL; + WriterT* instance = (WriterT*)handle; + delete instance; + return CV_ERROR_OK; +} + +static +CvResult CV_API_CALL cv_writer_get_prop(CvPluginWriter /*handle*/, int /*prop*/, CV_OUT double* /*val*/) +{ + return CV_ERROR_FAIL; +} + +static +CvResult CV_API_CALL cv_writer_set_prop(CvPluginWriter /*handle*/, int /*prop*/, double /*val*/) +{ + return CV_ERROR_FAIL; +} + +static +CvResult CV_API_CALL cv_writer_write(CvPluginWriter handle, const unsigned char* data, int step, int width, int height, int cn) +{ + if (!handle) + return CV_ERROR_FAIL; + try + { + CV_Assert(step >= 0); + WriterT* instance = (WriterT*)handle; + Size sz(width, height); + Mat img(sz, CV_MAKETYPE(CV_8U, cn), (void*)data, (size_t)step); + instance->write(img); + return CV_ERROR_OK; + } + catch (...) + { + return CV_ERROR_FAIL; + } +} + +static const OpenCV_VideoIO_Plugin_API_preview plugin_api_v0 = +{ + { + sizeof(OpenCV_VideoIO_Plugin_API_preview), ABI_VERSION, API_VERSION, + CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS, + "Microsoft Media Foundation OpenCV Video I/O plugin" + }, + /* 1*/CAP_MSMF, + /* 2*/cv_capture_open, + /* 3*/cv_capture_release, + /* 4*/cv_capture_get_prop, + /* 5*/cv_capture_set_prop, + /* 6*/cv_capture_grab, + /* 7*/cv_capture_retrieve, + /* 8*/cv_writer_open, + /* 9*/cv_writer_release, + /* 10*/cv_writer_get_prop, + /* 11*/cv_writer_set_prop, + /* 12*/cv_writer_write +}; + +} // namespace + +const OpenCV_VideoIO_Plugin_API_preview* opencv_videoio_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT +{ + if (requested_abi_version != 0) + return NULL; + if (requested_api_version != 0) + return NULL; + return &cv::plugin_api_v0; +} + +#endif // BUILD_PLUGIN diff --git a/modules/videoio/src/videoio_registry.cpp b/modules/videoio/src/videoio_registry.cpp index a98b907a46..b5798db80e 100644 --- a/modules/videoio/src/videoio_registry.cpp +++ b/modules/videoio/src/videoio_registry.cpp @@ -83,9 +83,13 @@ static const struct VideoBackendInfo builtin_backends[] = #ifdef WINRT_VIDEO DECLARE_STATIC_BACKEND(CAP_WINRT, "WINRT", MODE_CAPTURE_BY_INDEX, 0, create_WRT_capture, 0), #endif + #ifdef HAVE_MSMF DECLARE_STATIC_BACKEND(CAP_MSMF, "MSMF", MODE_CAPTURE_ALL | MODE_WRITER, cvCreateCapture_MSMF, cvCreateCapture_MSMF, cvCreateVideoWriter_MSMF), +#elif defined(ENABLE_PLUGINS) + DECLARE_DYNAMIC_BACKEND(CAP_MSMF, "MSMF", MODE_CAPTURE_ALL | MODE_WRITER), #endif + #ifdef HAVE_DSHOW DECLARE_STATIC_BACKEND(CAP_DSHOW, "DSHOW", MODE_CAPTURE_BY_INDEX, 0, create_DShow_capture, 0), #endif diff --git a/modules/videoio/test/test_video_io.cpp b/modules/videoio/test/test_video_io.cpp index 16db1f5e18..c5f7e75403 100644 --- a/modules/videoio/test/test_video_io.cpp +++ b/modules/videoio/test/test_video_io.cpp @@ -323,7 +323,7 @@ static const VideoCaptureAPIs backend_params[] = { CAP_AVFOUNDATION, #endif -#ifdef HAVE_MSMF +#ifdef _WIN32 CAP_MSMF, #endif @@ -366,7 +366,7 @@ inline static std::ostream &operator<<(std::ostream &out, const Ext_Fourcc_PSNR static Ext_Fourcc_PSNR synthetic_params[] = { -#ifdef HAVE_MSMF +#ifdef _WIN32 #if !defined(_M_ARM) {"wmv", "WMV1", 30.f, CAP_MSMF}, {"wmv", "WMV2", 30.f, CAP_MSMF},