diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 38d59c225c..24b5caf331 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -64,18 +64,24 @@ if(DEFINED WINRT AND NOT DEFINED WINRT_8_0 AND NOT DEFINED ENABLE_WINRT_MODE_NAT ${CMAKE_CURRENT_LIST_DIR}/src/cap_winrt/MediaStreamSink.hpp) endif() +include(${CMAKE_CURRENT_LIST_DIR}/cmake/plugin.cmake) + set(tgts) if(TARGET ocv.3rdparty.mediasdk) - list(APPEND videoio_srcs - ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_common.cpp - ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_reader.cpp - ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_writer.cpp) - list(APPEND videoio_hdrs - ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_common.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_reader.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_writer.hpp) - list(APPEND tgts ocv.3rdparty.mediasdk) + if("mfx" IN_LIST VIDEOIO_PLUGIN_LIST) + ocv_create_builtin_videoio_plugin("opencv_videoio_intel_mfx" ocv.3rdparty.mediasdk "cap_mfx_common.cpp" "cap_mfx_reader.cpp" "cap_mfx_writer.cpp" "cap_mfx_plugin.cpp") + else() + list(APPEND videoio_srcs + ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_common.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_reader.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_writer.cpp) + list(APPEND videoio_hdrs + ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_common.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_reader.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/cap_mfx_writer.hpp) + list(APPEND tgts ocv.3rdparty.mediasdk) + endif() endif() if(TARGET ocv.3rdparty.dshow) @@ -100,8 +106,6 @@ if(TARGET ocv.3rdparty.dc1394_2) list(APPEND tgts ocv.3rdparty.dc1394_2) endif() -include(${CMAKE_CURRENT_LIST_DIR}/cmake/plugin.cmake) - if(TARGET ocv.3rdparty.gstreamer) if("gstreamer" IN_LIST VIDEOIO_PLUGIN_LIST) ocv_create_builtin_videoio_plugin("opencv_videoio_gstreamer" ocv.3rdparty.gstreamer "cap_gstreamer.cpp") diff --git a/modules/videoio/cmake/plugin.cmake b/modules/videoio/cmake/plugin.cmake index 8e27401910..be73948ff3 100644 --- a/modules/videoio/cmake/plugin.cmake +++ b/modules/videoio/cmake/plugin.cmake @@ -1,4 +1,4 @@ -function(ocv_create_builtin_videoio_plugin name target videoio_src_file) +function(ocv_create_builtin_videoio_plugin name target) ocv_debug_message("ocv_create_builtin_videoio_plugin(${ARGV})") @@ -11,9 +11,11 @@ function(ocv_create_builtin_videoio_plugin name target videoio_src_file) message(STATUS "Video I/O: add builtin plugin '${name}'") - add_library(${name} MODULE - "${CMAKE_CURRENT_LIST_DIR}/src/${videoio_src_file}" - ) + foreach(src ${ARGN}) + list(APPEND sources "${CMAKE_CURRENT_LIST_DIR}/src/${src}") + endforeach() + + add_library(${name} MODULE ${sources}) target_include_directories(${name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") target_compile_definitions(${name} PRIVATE BUILD_PLUGIN) target_link_libraries(${name} PRIVATE ${target}) diff --git a/modules/videoio/src/cap_mfx_common.cpp b/modules/videoio/src/cap_mfx_common.cpp index 705d180687..71a8525c25 100644 --- a/modules/videoio/src/cap_mfx_common.cpp +++ b/modules/videoio/src/cap_mfx_common.cpp @@ -196,5 +196,3 @@ bool WriteBitstream::isOpened() const { return output.is_open(); } - -//================================================================================================== diff --git a/modules/videoio/src/cap_mfx_plugin.cpp b/modules/videoio/src/cap_mfx_plugin.cpp new file mode 100644 index 0000000000..098f4d7d12 --- /dev/null +++ b/modules/videoio/src/cap_mfx_plugin.cpp @@ -0,0 +1,220 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#if defined(BUILD_PLUGIN) + +#include +#include "cap_mfx_reader.hpp" +#include "cap_mfx_writer.hpp" +#include "plugin_api.hpp" + +using namespace std; + +namespace cv { + +static +CvResult CV_API_CALL cv_capture_open(const char* filename, int, CV_OUT CvPluginCapture* handle) +{ + if (!handle) + return CV_ERROR_FAIL; + *handle = NULL; + if (!filename) + return CV_ERROR_FAIL; + VideoCapture_IntelMFX *cap = 0; + try + { + if (filename) + { + cap = new VideoCapture_IntelMFX(string(filename)); + 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) + return CV_ERROR_FAIL; + VideoCapture_IntelMFX* instance = (VideoCapture_IntelMFX*)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 + { + VideoCapture_IntelMFX* instance = (VideoCapture_IntelMFX*)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 + { + VideoCapture_IntelMFX* instance = (VideoCapture_IntelMFX*)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 + { + VideoCapture_IntelMFX* instance = (VideoCapture_IntelMFX*)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 + { + 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 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) +{ + VideoWriter_IntelMFX* wrt = 0; + try + { + wrt = new VideoWriter_IntelMFX(filename, fourcc, fps, Size(width, height), isColor); + if(wrt->isOpened()) + { + *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; + VideoWriter_IntelMFX* instance = (VideoWriter_IntelMFX*)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 + { + VideoWriter_IntelMFX* instance = (VideoWriter_IntelMFX*)handle; + Mat img(Size(width, height), CV_MAKETYPE(CV_8U, cn), const_cast(data), 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, + "MediaSDK OpenCV Video I/O plugin" + }, + /* 1*/CAP_INTEL_MFX, + /* 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 cec435b75b..c35f2b2f78 100644 --- a/modules/videoio/src/videoio_registry.cpp +++ b/modules/videoio/src/videoio_registry.cpp @@ -70,6 +70,8 @@ static const struct VideoBackendInfo builtin_backends[] = #ifdef HAVE_MFX // Media SDK DECLARE_STATIC_BACKEND(CAP_INTEL_MFX, "INTEL_MFX", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, create_MFX_capture, 0, create_MFX_writer), +#elif defined(ENABLE_PLUGINS) + DECLARE_DYNAMIC_BACKEND(CAP_INTEL_MFX, "INTEL_MFX", MODE_CAPTURE_BY_FILENAME | MODE_WRITER), #endif // Apple platform diff --git a/modules/videoio/test/test_mfx.cpp b/modules/videoio/test/test_mfx.cpp index 2f69ea75db..3729a17cdc 100644 --- a/modules/videoio/test/test_mfx.cpp +++ b/modules/videoio/test/test_mfx.cpp @@ -4,12 +4,13 @@ #include "test_precomp.hpp" -#ifdef HAVE_MFX - namespace opencv_test { namespace { TEST(videoio_mfx, read_invalid) { + if (!videoio_registry::hasBackend(CAP_INTEL_MFX)) + throw SkipTestException("MediaSDK backend was not found"); + VideoCapture cap; ASSERT_NO_THROW(cap.open("nonexistent-file", CAP_INTEL_MFX)); ASSERT_FALSE(cap.isOpened()); @@ -20,6 +21,9 @@ TEST(videoio_mfx, read_invalid) TEST(videoio_mfx, write_invalid) { + if (!videoio_registry::hasBackend(CAP_INTEL_MFX)) + throw SkipTestException("MediaSDK backend was not found"); + const string filename = cv::tempfile(".264"); VideoWriter writer; bool res = true; @@ -84,6 +88,9 @@ typedef testing::TestWithParam< Size_FPS_Ext > videoio_mfx; TEST_P(videoio_mfx, read_write_raw) { + if (!videoio_registry::hasBackend(CAP_INTEL_MFX)) + throw SkipTestException("MediaSDK backend was not found"); + const Size FRAME_SIZE = get<0>(GetParam()); const double FPS = get<1>(GetParam()); const char *ext = get<2>(GetParam()); @@ -144,5 +151,3 @@ INSTANTIATE_TEST_CASE_P(videoio, videoio_mfx, testing::Values(".mpeg2", ".264", ".265"))); }} // namespace - -#endif