From 4c74e6d89d35dc45a3889d96158989352f73b1db Mon Sep 17 00:00:00 2001 From: Alexey Smirnov Date: Fri, 23 Sep 2022 12:08:29 +0100 Subject: [PATCH] Copy mpashchenkov's changes Minor refactoring Partially address review comments Move DX-related stuff from the sample to a default source Simplify the default OneVPL config Address minor review comments Add class for the default VPL source WIP: Add initial stub for tests with description Removing default vpl source and minor refactoring Refactor default files Fix build and application crash Address review comments Add test on VPL + OCL interaction compared to CPU behavior Fix test --- modules/gapi/CMakeLists.txt | 13 ++- .../include/opencv2/gapi/ocl/goclkernel.hpp | 4 + .../opencv2/gapi/streaming/onevpl/default.hpp | 29 +++++ ..._infer_with_advanced_device_selection.cpp} | 0 .../samples/onevpl_source_to_bgr_conv.cpp | 106 ++++++++++++++++++ modules/gapi/src/backends/ocl/goclbackend.cpp | 4 +- modules/gapi/src/backends/ocl/goclcore.cpp | 95 ++++++++++++++++ .../surface/cpu_frame_adapter.cpp | 1 - .../surface/dx11_frame_adapter.cpp | 17 ++- .../surface/dx11_frame_adapter.hpp | 5 + .../onevpl/cfg_param_device_selector.hpp | 2 +- modules/gapi/src/streaming/onevpl/default.cpp | 52 +++++++++ .../engine/decode/decode_engine_legacy.cpp | 3 +- .../onevpl/engine/preproc/preproc_engine.cpp | 2 +- modules/gapi/src/streaming/onevpl/utils.cpp | 1 + .../gapi_streaming_vpl_core_test.cpp | 68 +++++++++++ 16 files changed, 386 insertions(+), 16 deletions(-) create mode 100644 modules/gapi/include/opencv2/gapi/streaming/onevpl/default.hpp rename modules/gapi/samples/{onevpl_infer_single_roi.cpp => onevpl_infer_with_advanced_device_selection.cpp} (100%) create mode 100644 modules/gapi/samples/onevpl_source_to_bgr_conv.cpp create mode 100644 modules/gapi/src/streaming/onevpl/default.cpp diff --git a/modules/gapi/CMakeLists.txt b/modules/gapi/CMakeLists.txt index 2a9d598bb8..a25af7a5c2 100644 --- a/modules/gapi/CMakeLists.txt +++ b/modules/gapi/CMakeLists.txt @@ -188,6 +188,7 @@ set(gapi_srcs src/streaming/onevpl/cfg_params.cpp src/streaming/onevpl/cfg_params_parser.cpp src/streaming/onevpl/utils.cpp + src/streaming/onevpl/default.cpp src/streaming/onevpl/data_provider_interface_exception.cpp src/streaming/onevpl/accelerators/surface/base_frame_adapter.cpp src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp @@ -367,20 +368,20 @@ ocv_add_samples() # Required for sample with inference on host -if(TARGET example_gapi_onevpl_infer_single_roi) +if(TARGET example_gapi_onevpl_infer_with_advanced_device_selection) if(TARGET ocv.3rdparty.openvino AND OPENCV_GAPI_WITH_OPENVINO) - ocv_target_link_libraries(example_gapi_onevpl_infer_single_roi PRIVATE ocv.3rdparty.openvino) + ocv_target_link_libraries(example_gapi_onevpl_infer_with_advanced_device_selection PRIVATE ocv.3rdparty.openvino) endif() if(HAVE_DIRECTX AND HAVE_D3D11) - ocv_target_link_libraries(example_gapi_onevpl_infer_single_roi PRIVATE d3d11 dxgi) + ocv_target_link_libraries(example_gapi_onevpl_infer_with_advanced_device_selection PRIVATE d3d11 dxgi) endif() if(HAVE_D3D11 AND HAVE_OPENCL) - ocv_target_include_directories(example_gapi_onevpl_infer_single_roi SYSTEM PRIVATE ${OPENCL_INCLUDE_DIRS}) + ocv_target_include_directories(example_gapi_onevpl_infer_with_advanced_device_selection SYSTEM PRIVATE ${OPENCL_INCLUDE_DIRS}) endif() if(UNIX AND HAVE_VA) message ("GAPI VPL samples with VAAPI") - ocv_target_include_directories(example_gapi_onevpl_infer_single_roi SYSTEM PRIVATE ${VA_INCLUDE_DIR}) - ocv_target_link_libraries(example_gapi_onevpl_infer_single_roi PRIVATE ${VA_LIBRARIES}) + ocv_target_include_directories(example_gapi_onevpl_infer_with_advanced_device_selection SYSTEM PRIVATE ${VA_INCLUDE_DIR}) + ocv_target_link_libraries(example_gapi_onevpl_infer_with_advanced_device_selection PRIVATE ${VA_LIBRARIES}) endif() endif() diff --git a/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp b/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp index 6a2f1df769..b70b54267d 100644 --- a/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp +++ b/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp @@ -119,6 +119,10 @@ template struct ocl_get_in > { static const std::vector& get(GOCLContext &ctx, int idx) { return ctx.inArg(idx).rref(); } }; +template<> struct ocl_get_in +{ + static cv::MediaFrame get(GOCLContext &ctx, int idx) { return ctx.inArg(idx); } +}; template struct ocl_get_in > { static const U& get(GOCLContext &ctx, int idx) { return ctx.inArg(idx).rref(); } diff --git a/modules/gapi/include/opencv2/gapi/streaming/onevpl/default.hpp b/modules/gapi/include/opencv2/gapi/streaming/onevpl/default.hpp new file mode 100644 index 0000000000..8b547e1aba --- /dev/null +++ b/modules/gapi/include/opencv2/gapi/streaming/onevpl/default.hpp @@ -0,0 +1,29 @@ +// 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. +// +// Copyright (C) 2022 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_ONEVPL_UTILS_HPP +#define OPENCV_GAPI_STREAMING_ONEVPL_UTILS_HPP + +#include // GAPI_EXPORTS +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +/** + * @brief Provides default device selector based on config. + */ +GAPI_EXPORTS std::shared_ptr getDefaultDeviceSelector(const std::vector& cfg_params); + +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_ONEVPL_UTILS_HPP diff --git a/modules/gapi/samples/onevpl_infer_single_roi.cpp b/modules/gapi/samples/onevpl_infer_with_advanced_device_selection.cpp similarity index 100% rename from modules/gapi/samples/onevpl_infer_single_roi.cpp rename to modules/gapi/samples/onevpl_infer_with_advanced_device_selection.cpp diff --git a/modules/gapi/samples/onevpl_source_to_bgr_conv.cpp b/modules/gapi/samples/onevpl_source_to_bgr_conv.cpp new file mode 100644 index 0000000000..660d7ed9a8 --- /dev/null +++ b/modules/gapi/samples/onevpl_source_to_bgr_conv.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include // CommandLineParser +#include + +const std::string about = + "This is an example presents decoding on GPU using VPL Source and passing it to OpenCL backend"; +const std::string keys = + "{ h help | | Print this help message }" + "{ input | | Path to the input video file. Use .avi extension }" + "{ accel_mode | mfxImplDescription.AccelerationMode:MFX_ACCEL_MODE_VIA_D3D11 | Acceleration mode for VPL }"; + +namespace { +namespace cfg { +// FIXME: Move OneVPL arguments parser to a single place +typename cv::gapi::wip::onevpl::CfgParam create_from_string(const std::string &line); +} // namespace cfg +} // anonymous namespace + +int main(int argc, char *argv[]) { + cv::CommandLineParser cmd(argc, argv, keys); + cmd.about(about); + if (cmd.has("help")) { + cmd.printMessage(); + return 0; + } + + // Get file name + const auto input = cmd.get("input"); + const auto accel_mode = cmd.get("accel_mode"); + + // Create VPL config + std::vector source_cfgs; + source_cfgs.push_back(cfg::create_from_string(accel_mode)); + + // Create VPL-based source + std::shared_ptr default_device_selector = + cv::gapi::wip::onevpl::getDefaultDeviceSelector(source_cfgs); + + cv::gapi::wip::IStreamSource::Ptr source = cv::gapi::wip::make_onevpl_src(input, source_cfgs, + default_device_selector); + + // Build the graph + cv::GFrame in; // input frame from VPL source + auto bgr_gmat = cv::gapi::streaming::BGR(in); // conversion from VPL source frame to BGR UMat + auto out = cv::gapi::blur(bgr_gmat, cv::Size(4,4)); // ocl kernel of blur operation + + cv::GStreamingCompiled pipeline = cv::GComputation(cv::GIn(in), cv::GOut(out)) + .compileStreaming(cv::compile_args(cv::gapi::core::ocl::kernels())); + pipeline.setSource(std::move(source)); + + // The execution part + size_t frames = 0u; + cv::TickMeter tm; + cv::Mat outMat; + + pipeline.start(); + tm.start(); + + while (pipeline.pull(cv::gout(outMat))) { + cv::imshow("OutVideo", outMat); + cv::waitKey(1); + ++frames; + } + tm.stop(); + std::cout << "Processed " << frames << " frames" << " (" << frames / tm.getTimeSec() << " FPS)" << std::endl; + + return 0; +} + +namespace { +namespace cfg { +typename cv::gapi::wip::onevpl::CfgParam create_from_string(const std::string &line) { + using namespace cv::gapi::wip; + + if (line.empty()) { + throw std::runtime_error("Cannot parse CfgParam from emply line"); + } + + std::string::size_type name_endline_pos = line.find(':'); + if (name_endline_pos == std::string::npos) { + throw std::runtime_error("Cannot parse CfgParam from: " + line + + "\nExpected separator \":\""); + } + + std::string name = line.substr(0, name_endline_pos); + std::string value = line.substr(name_endline_pos + 1); + + return cv::gapi::wip::onevpl::CfgParam::create(name, value, + /* vpp params strongly optional */ + name.find("vpp.") == std::string::npos); +} +} // namespace cfg +} // anonymous namespace diff --git a/modules/gapi/src/backends/ocl/goclbackend.cpp b/modules/gapi/src/backends/ocl/goclbackend.cpp index dba2b27b59..9c6d7154e4 100644 --- a/modules/gapi/src/backends/ocl/goclbackend.cpp +++ b/modules/gapi/src/backends/ocl/goclbackend.cpp @@ -114,7 +114,8 @@ cv::GArg cv::gimpl::GOCLExecutable::packArg(const GArg &arg) GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT && arg.kind != cv::detail::ArgKind::GSCALAR && arg.kind != cv::detail::ArgKind::GARRAY - && arg.kind != cv::detail::ArgKind::GOPAQUE); + && arg.kind != cv::detail::ArgKind::GOPAQUE + && arg.kind != cv::detail::ArgKind::GFRAME); if (arg.kind != cv::detail::ArgKind::GOBJREF) { @@ -136,6 +137,7 @@ cv::GArg cv::gimpl::GOCLExecutable::packArg(const GArg &arg) // Note: .at() is intentional for GOpaque as object MUST be already there // (and constructed by either bindIn/Out or resetInternal) case GShape::GOPAQUE: return GArg(m_res.slot().at(ref.id)); + case GShape::GFRAME: return GArg(m_res.slot().at(ref.id)); default: util::throw_error(std::logic_error("Unsupported GShape type")); break; diff --git a/modules/gapi/src/backends/ocl/goclcore.cpp b/modules/gapi/src/backends/ocl/goclcore.cpp index f3c5aa32bc..19fa54a40a 100644 --- a/modules/gapi/src/backends/ocl/goclcore.cpp +++ b/modules/gapi/src/backends/ocl/goclcore.cpp @@ -6,11 +6,32 @@ #include "precomp.hpp" +#include "logger.hpp" #include #include +#include + #include "backends/ocl/goclcore.hpp" +#ifdef HAVE_DIRECTX +#ifdef HAVE_D3D11 +#pragma comment(lib,"d3d11.lib") + +// get rid of generate macro max/min/etc from DX side +#define D3D11_NO_HELPERS +#define NOMINMAX +#include +#pragma comment(lib, "dxgi") +#undef NOMINMAX +#undef D3D11_NO_HELPERS +#include +#endif // HAVE_D3D11 +#endif // HAVE_DIRECTX + +#include +#include "streaming/onevpl/accelerators/surface/dx11_frame_adapter.hpp" + GAPI_OCL_KERNEL(GOCLAdd, cv::gapi::core::GAdd) { static void run(const cv::UMat& a, const cv::UMat& b, int dtype, cv::UMat& out) @@ -523,6 +544,79 @@ GAPI_OCL_KERNEL(GOCLTranspose, cv::gapi::core::GTranspose) } }; +GAPI_OCL_KERNEL(GOCLBGR, cv::gapi::streaming::GBGR) +{ + static void run(const cv::MediaFrame& in, cv::UMat& out) + { + cv::util::suppress_unused_warning(in); + cv::util::suppress_unused_warning(out); +#ifdef HAVE_DIRECTX +#ifdef HAVE_D3D11 +#ifdef HAVE_ONEVPL + auto d = in.desc(); + if (d.fmt != cv::MediaFormat::NV12) + { + GAPI_LOG_FATAL(nullptr, "Unsupported format provided: " << static_cast(d.fmt) << + ". Expected cv::MediaFormat::NV12."); + cv::util::throw_error(std::logic_error("Unsupported MediaFrame format provided")); + } + + // FIXME: consider a better solution. + // Current approach cannot be easily extended for other adapters (getHandle). + auto adapterPtr = in.get(); + if (adapterPtr == nullptr) + { + GAPI_LOG_FATAL(nullptr, "Unsupported adapter type. Only VPLMediaFrameDX11Adapter is supported"); + cv::util::throw_error(std::logic_error("Unsupported adapter type. Only VPLMediaFrameDX11Adapter is supported")); + } + + auto params = adapterPtr->getHandle(); + auto handle = cv::util::any_cast(params); + ID3D11Texture2D* texture = reinterpret_cast(handle.first); + if (texture == nullptr) + { + GAPI_LOG_FATAL(nullptr, "mfxHDLPair contains ID3D11Texture2D that is nullptr. Handle address" << + reinterpret_cast(handle.first)); + cv::util::throw_error(std::logic_error("mfxHDLPair contains ID3D11Texture2D that is nullptr")); + } + + // FIXME: Assuming here that we only have 1 device + // TODO: Textures are reusable, so to improve the peroformance here + // consider creating a hash map texture <-> device/ctx + static thread_local ID3D11Device* pD3D11Device = nullptr; + if (pD3D11Device == nullptr) + { + texture->GetDevice(&pD3D11Device); + } + if (pD3D11Device == nullptr) + { + GAPI_LOG_FATAL(nullptr, "D3D11Texture2D::GetDevice returns pD3D11Device that is nullptr"); + cv::util::throw_error(std::logic_error("D3D11Texture2D::GetDevice returns pD3D11Device that is nullptr")); + } + + // FIXME: assuming here that the context is always the same + // TODO: Textures are reusable, so to improve the peroformance here + // consider creating a hash map texture <-> device/ctx + static thread_local cv::ocl::Context ctx = cv::directx::ocl::initializeContextFromD3D11Device(pD3D11Device); + if (ctx.ptr() == nullptr) + { + GAPI_LOG_FATAL(nullptr, "initializeContextFromD3D11Device returned null context"); + cv::util::throw_error(std::logic_error("initializeContextFromD3D11Device returned null context")); + } + + cv::directx::convertFromD3D11Texture2D(texture, out); +#else + GAPI_LOG_FATAL(nullptr, "HAVE_ONEVPL is not set. Please, check your cmake flags"); + cv::util::throw_error(std::logic_error("HAVE_ONEVPL is not set. Please, check your cmake flags")); +#endif // HAVE_ONEVPL +#else + GAPI_LOG_FATAL(nullptr, "HAVE_D3D11 or HAVE_DIRECTX is not set. Please, check your cmake flags"); + cv::util::throw_error(std::logic_error("HAVE_D3D11 or HAVE_DIRECTX is not set. Please, check your cmake flags")); +#endif // HAVE_D3D11 +#endif // HAVE_DIRECTX + } +}; + cv::GKernelPackage cv::gapi::core::ocl::kernels() { static auto pkg = cv::gapi::kernels @@ -587,6 +681,7 @@ cv::GKernelPackage cv::gapi::core::ocl::kernels() , GOCLLUT , GOCLConvertTo , GOCLTranspose + , GOCLBGR >(); return pkg; } diff --git a/modules/gapi/src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp b/modules/gapi/src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp index 24a5b9fb7f..f78d97d571 100644 --- a/modules/gapi/src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp +++ b/modules/gapi/src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp @@ -65,7 +65,6 @@ MediaFrame::View VPLMediaFrameCPUAdapter::access(MediaFrame::Access) { cv::util::any VPLMediaFrameCPUAdapter::blobParams() const { throw std::runtime_error("VPLMediaFrameCPUAdapter::blobParams() is not implemented"); - return {}; } void VPLMediaFrameCPUAdapter::serialize(cv::gapi::s11n::IOStream&) { diff --git a/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.cpp b/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.cpp index fad26e50a8..3744ddc8ce 100644 --- a/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.cpp +++ b/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.cpp @@ -114,17 +114,24 @@ MediaFrame::View VPLMediaFrameDX11Adapter::access(MediaFrame::Access mode) { } } +mfxHDLPair VPLMediaFrameDX11Adapter::getHandle() const { + auto surface_ptr_copy = get_surface(); + const Surface::data_t& data = surface_ptr_copy->get_data(); + NativeHandleAdapter* native_handle_getter = reinterpret_cast(data.MemId); + + mfxHDLPair handle{}; + native_handle_getter->get_handle(data.MemId, reinterpret_cast(handle)); + return handle; +} + cv::util::any VPLMediaFrameDX11Adapter::blobParams() const { /*GAPI_Assert(false && "VPLMediaFrameDX11Adapter::blobParams() is not fully integrated" "in OpenVINO InferenceEngine and would be temporary disable.");*/ #ifdef HAVE_INF_ENGINE + mfxHDLPair handle = getHandle(); + auto surface_ptr_copy = get_surface(); - Surface::data_t& data = surface_ptr_copy->get_data(); const Surface::info_t& info = surface_ptr_copy->get_info(); - NativeHandleAdapter* native_handle_getter = reinterpret_cast(data.MemId); - - mfxHDLPair handle{}; - native_handle_getter->get_handle(data.MemId, reinterpret_cast(handle)); GAPI_Assert(frame_desc.fmt == MediaFormat::NV12 && "blobParams() for VPLMediaFrameDX11Adapter supports NV12 only"); diff --git a/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.hpp b/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.hpp index 39528ca6a5..a5eddbb407 100644 --- a/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.hpp +++ b/modules/gapi/src/streaming/onevpl/accelerators/surface/dx11_frame_adapter.hpp @@ -37,6 +37,11 @@ public: GAPI_EXPORTS ~VPLMediaFrameDX11Adapter(); MediaFrame::View access(MediaFrame::Access) override; + // FIXME: Consider a better solution since this approach + // is not easily extendable for other adapters (oclcore.cpp) + // FIXME: Use with caution since the handle might become invalid + // due to reference counting + mfxHDLPair getHandle() const; // The default implementation does nothing cv::util::any blobParams() const override; void serialize(cv::gapi::s11n::IOStream&) override; diff --git a/modules/gapi/src/streaming/onevpl/cfg_param_device_selector.hpp b/modules/gapi/src/streaming/onevpl/cfg_param_device_selector.hpp index f7672ce924..18b468fd86 100644 --- a/modules/gapi/src/streaming/onevpl/cfg_param_device_selector.hpp +++ b/modules/gapi/src/streaming/onevpl/cfg_param_device_selector.hpp @@ -20,7 +20,7 @@ namespace gapi { namespace wip { namespace onevpl { -class PlatformSpecificParams; +struct PlatformSpecificParams; std::vector update_param_with_accel_type(std::vector &¶m_array, AccelType type); struct GAPI_EXPORTS CfgParamDeviceSelector final: public IDeviceSelector { diff --git a/modules/gapi/src/streaming/onevpl/default.cpp b/modules/gapi/src/streaming/onevpl/default.cpp new file mode 100644 index 0000000000..0456915a00 --- /dev/null +++ b/modules/gapi/src/streaming/onevpl/default.cpp @@ -0,0 +1,52 @@ +// 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. +// +// Copyright (C) 2022 Intel Corporation + +#include +#include + +#include +#include +#include + +#include "cfg_param_device_selector.hpp" + +#ifdef HAVE_ONEVPL + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +std::shared_ptr getDefaultDeviceSelector(const std::vector& cfg_params) { + std::shared_ptr default_accel_contex(new CfgParamDeviceSelector(cfg_params)); + + return default_accel_contex; +} + +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#else // HAVE_ONEVPL + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +std::shared_ptr getDefaultDeviceSelector(const std::vector&) { + std::cerr << "Cannot utilize getDefaultVPLDeviceAndCtx without HAVE_ONEVPL enabled" << std::endl; + util::throw_error(std::logic_error("Cannot utilize getDefaultVPLDeviceAndCtx without HAVE_ONEVPL enabled")); + return nullptr; +} + +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // HAVE_ONEVPL diff --git a/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp b/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp index 0ab8301799..8a35cca063 100644 --- a/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp +++ b/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp @@ -251,7 +251,8 @@ VPLLegacyDecodeEngine::SessionParam VPLLegacyDecodeEngine::prepare_session_param } - decRequest.Type |= MFX_MEMTYPE_EXTERNAL_FRAME | MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_VPPIN; + decRequest.Type |= MFX_MEMTYPE_EXTERNAL_FRAME | MFX_MEMTYPE_FROM_DECODE | + MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_SHARED_RESOURCE; VPLAccelerationPolicy::pool_key_t decode_pool_key = acceleration_policy->create_surface_pool(decRequest, mfxDecParams.mfx.FrameInfo); diff --git a/modules/gapi/src/streaming/onevpl/engine/preproc/preproc_engine.cpp b/modules/gapi/src/streaming/onevpl/engine/preproc/preproc_engine.cpp index 10ce92e20a..d0c4a85f38 100644 --- a/modules/gapi/src/streaming/onevpl/engine/preproc/preproc_engine.cpp +++ b/modules/gapi/src/streaming/onevpl/engine/preproc/preproc_engine.cpp @@ -281,7 +281,7 @@ pp_session VPPPreprocEngine::initialize_preproc(const pp_params& initial_frame_p vppRequests[1].AllocId = std::numeric_limits::max() - request_id++; GAPI_Assert(request_id != std::numeric_limits::max() && "Something wrong"); - vppRequests[1].Type |= MFX_MEMTYPE_FROM_VPPIN; + vppRequests[1].Type |= MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_SHARED_RESOURCE; vpp_out_pool_key = acceleration_policy->create_surface_pool(vppRequests[1], mfxVPPParams.vpp.Out); diff --git a/modules/gapi/src/streaming/onevpl/utils.cpp b/modules/gapi/src/streaming/onevpl/utils.cpp index efd1618b71..a5513f5377 100644 --- a/modules/gapi/src/streaming/onevpl/utils.cpp +++ b/modules/gapi/src/streaming/onevpl/utils.cpp @@ -429,4 +429,5 @@ std::string ext_mem_frame_type_to_cstr(int type) { } // namespace wip } // namespace gapi } // namespace cv + #endif // HAVE_ONEVPL diff --git a/modules/gapi/test/streaming/gapi_streaming_vpl_core_test.cpp b/modules/gapi/test/streaming/gapi_streaming_vpl_core_test.cpp index d83b09d7d3..cabfe15d7e 100644 --- a/modules/gapi/test/streaming/gapi_streaming_vpl_core_test.cpp +++ b/modules/gapi/test/streaming/gapi_streaming_vpl_core_test.cpp @@ -8,6 +8,7 @@ #include "../test_precomp.hpp" #include "../common/gapi_streaming_tests_common.hpp" +#include "../common/gapi_tests_common.hpp" #include #include @@ -29,6 +30,7 @@ #ifdef HAVE_ONEVPL #include +#include #include "streaming/onevpl/file_data_provider.hpp" #include "streaming/onevpl/cfg_param_device_selector.hpp" @@ -327,6 +329,72 @@ TEST(OneVPL_Source_CPU_FrameAdapter, InitFrameAdapter) EXPECT_TRUE(0 == surf->get_locks_count()); } +TEST(OneVPL_Source_Default_Source_With_OCL_Backend, Accuracy) +{ + using namespace cv::gapi::wip::onevpl; + + auto create_from_string = [](const std::string& line){ + std::string::size_type name_endline_pos = line.find(':'); + std::string name = line.substr(0, name_endline_pos); + std::string value = line.substr(name_endline_pos + 1); + return CfgParam::create(name, value); + }; + + std::vector source_cfgs; + source_cfgs.push_back(create_from_string("mfxImplDescription.AccelerationMode:MFX_ACCEL_MODE_VIA_D3D11")); + + // Create VPL-based source + std::shared_ptr default_device_selector = getDefaultDeviceSelector(source_cfgs); + + cv::gapi::wip::IStreamSource::Ptr source; + cv::gapi::wip::IStreamSource::Ptr source_cpu; + + auto input = findDataFile("cv/video/768x576.avi"); + try { + source = cv::gapi::wip::make_onevpl_src(input, source_cfgs, default_device_selector); + source_cpu = cv::gapi::wip::make_onevpl_src(input, source_cfgs, default_device_selector); + } catch(...) { + throw SkipTestException("Video file can not be opened"); + } + + // Build the graph w/ OCL backend + cv::GFrame in; // input frame from VPL source + auto bgr_gmat = cv::gapi::streaming::BGR(in); // conversion from VPL source frame to BGR UMat + auto out = cv::gapi::blur(bgr_gmat, cv::Size(4,4)); // ocl kernel of blur operation + + cv::GStreamingCompiled pipeline = cv::GComputation(cv::GIn(in), cv::GOut(out)) + .compileStreaming(std::move(cv::compile_args(cv::gapi::core::ocl::kernels()))); + pipeline.setSource(std::move(source)); + + cv::GStreamingCompiled pipeline_cpu = cv::GComputation(cv::GIn(in), cv::GOut(out)) + .compileStreaming(std::move(cv::compile_args(cv::gapi::core::cpu::kernels()))); + pipeline_cpu.setSource(std::move(source_cpu)); + + // The execution part + cv::Mat out_mat; + std::vector ocl_mats, cpu_mats; + + // Run the pipelines + pipeline.start(); + while (pipeline.pull(cv::gout(out_mat))) + { + ocl_mats.push_back(out_mat); + } + + pipeline_cpu.start(); + while (pipeline_cpu.pull(cv::gout(out_mat))) + { + cpu_mats.push_back(out_mat); + } + + // Compare results + // FIXME: investigate why 2 sources produce different number of frames sometimes + for (size_t i = 0; i < std::min(ocl_mats.size(), cpu_mats.size()); ++i) + { + EXPECT_TRUE(AbsTolerance(1).to_compare_obj()(ocl_mats[i], cpu_mats[i])); + } +} + TEST(OneVPL_Source_CPU_Accelerator, InitDestroy) { using cv::gapi::wip::onevpl::VPLCPUAccelerationPolicy;