Merge pull request #20570 from sivanov-work:vpl_source_data_adapter

G-API: oneVPL (simplification) Add data adapter & Cfg params

* Add cfg_param & data_provider

* Fix compilation after rebase

* Apply some comments

* Apply default ctor outside class definition comment

* Apply cfg param in source

* Fix compilation: add virtual dtor

* Move cfg_params in regular gapi src list

* Fix compilation: add export.hpp

* Add errno.h

* Add errno.h

* Apply namespace comment

* Add several Doxygen & rename cfg_param

* Fix build

* Update Doxygen docs for onevpl

* Fix typo
pull/20616/head
Sergey Ivanov 3 years ago committed by GitHub
parent b509a7060a
commit 65ef82a946
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      modules/gapi/CMakeLists.txt
  2. 88
      modules/gapi/include/opencv2/gapi/streaming/onevpl/cfg_params.hpp
  3. 74
      modules/gapi/include/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp
  4. 44
      modules/gapi/include/opencv2/gapi/streaming/onevpl/onevpl_source.hpp
  5. 64
      modules/gapi/include/opencv2/gapi/streaming/onevpl/source.hpp
  6. 51
      modules/gapi/samples/onevpl_infer_single_roi.cpp
  7. 137
      modules/gapi/src/streaming/onevpl/cfg_params.cpp
  8. 22
      modules/gapi/src/streaming/onevpl/data_provider_interface_exception.cpp
  9. 47
      modules/gapi/src/streaming/onevpl/file_data_provider.cpp
  10. 33
      modules/gapi/src/streaming/onevpl/file_data_provider.hpp
  11. 48
      modules/gapi/src/streaming/onevpl/onevpl_source.cpp
  12. 58
      modules/gapi/src/streaming/onevpl/source.cpp
  13. 22
      modules/gapi/src/streaming/onevpl/source_priv.cpp
  14. 13
      modules/gapi/src/streaming/onevpl/source_priv.hpp
  15. 70
      modules/gapi/test/streaming/gapi_streaming_tests.cpp

@ -164,8 +164,11 @@ set(gapi_srcs
src/backends/python/gpythonbackend.cpp src/backends/python/gpythonbackend.cpp
# Streaming source # Streaming source
src/streaming/onevpl/onevpl_source.cpp src/streaming/onevpl/source.cpp
src/streaming/onevpl/onevpl_source_priv.cpp src/streaming/onevpl/source_priv.cpp
src/streaming/onevpl/file_data_provider.cpp
src/streaming/onevpl/cfg_params.cpp
src/streaming/onevpl/data_provider_interface_exception.cpp
# Utils (ITT tracing) # Utils (ITT tracing)
src/utils/itt.cpp src/utils/itt.cpp

@ -0,0 +1,88 @@
// 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) 2021 Intel Corporation
#ifndef OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP
#define OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP
#include <map>
#include <memory>
#include <string>
#include <opencv2/gapi/streaming/source.hpp>
#include <opencv2/gapi/util/variant.hpp>
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
/**
* @brief Public class is using for creation of onevpl::GSource instances.
*
* Class members availaible through methods @ref CfgParam::get_name() and @ref CfgParam::get_value() are used by
* onevpl::GSource inner logic to create or find oneVPL particular implementation
* (software/hardware, specific API version and etc.).
*
* @note Because oneVPL may provide several implementations which are satisfying with multiple (or single one) @ref CfgParam
* criteria therefore it is possible to configure `preferred` parameters. This kind of CfgParams are created
* using `is_major = false` argument in @ref CfgParam::create method and are not used by creating oneVPL particular implementations.
* Instead they fill out a "score table" to select preferrable implementation from available list. Implementation are satisfying
* with most of these optional params would be chosen.
* If no one optional CfgParam params were present then first of available oneVPL implementation would be applied.
* Please get on https://spec.oneapi.io/versions/latest/elements/oneVPL/source/API_ref/VPL_disp_api_func.html?highlight=mfxcreateconfig#mfxsetconfigfilterproperty
* for using OneVPL configuration. In this schema `mfxU8 *name` represents @ref CfgParam::get_name() and
* `mfxVariant value` is @ref CfgParam::get_value()
*/
struct GAPI_EXPORTS CfgParam {
using name_t = std::string;
using value_t = cv::util::variant<uint8_t, int8_t,
uint16_t, int16_t,
uint32_t, int32_t,
uint64_t, int64_t,
float_t,
double_t,
void*,
std::string>;
/**
* Create onevp::GSource configuration parameter.
*
*@param name name of parameter.
*@param value value of parameter.
*@param is_major TRUE if parameter MUST be provided by OneVPL inner implementation, FALSE for optional (for resolve multiple available implementations).
*
*/
template<typename ValueType>
static CfgParam create(const std::string& name, ValueType&& value, bool is_major = true) {
CfgParam param(name, CfgParam::value_t(std::forward<ValueType>(value)), is_major);
return param;
}
struct Priv;
const name_t& get_name() const;
const value_t& get_value() const;
bool is_major() const;
bool operator==(const CfgParam& rhs) const;
bool operator< (const CfgParam& rhs) const;
bool operator!=(const CfgParam& rhs) const;
CfgParam& operator=(const CfgParam& src);
CfgParam& operator=(CfgParam&& src);
CfgParam(const CfgParam& src);
CfgParam(CfgParam&& src);
~CfgParam();
private:
CfgParam(const std::string& param_name, value_t&& param_value, bool is_major_param);
std::shared_ptr<Priv> m_priv;
};
} //namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP

@ -0,0 +1,74 @@
// 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) 2021 Intel Corporation
#ifndef GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP
#define GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP
#include <exception>
#include <string>
#include <opencv2/gapi/own/exports.hpp> // GAPI_EXPORTS
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
struct GAPI_EXPORTS DataProviderException : public std::exception {
virtual ~DataProviderException() {};
};
struct GAPI_EXPORTS DataProviderSystemErrorException : public DataProviderException {
DataProviderSystemErrorException(int error_code, const std::string& desription = std::string());
virtual ~DataProviderSystemErrorException();
virtual const char* what() const noexcept override;
private:
std::string reason;
};
/**
* @brief Public interface allows to customize extraction of video stream data
* used by onevpl::GSource instead of reading stream from file (by default).
*
* Interface implementation constructor MUST provide consistency and creates fully operable object.
* If error happened implementation MUST throw `DataProviderException` kind exceptions
*
* @note Interface implementation MUST manage stream and other constructed resources by itself to avoid any kind of leak.
* For simple interface implementation example please see `StreamDataProvider` in `tests/streaming/gapi_streaming_tests.cpp`
*/
struct GAPI_EXPORTS IDataProvider {
using Ptr = std::shared_ptr<IDataProvider>;
virtual ~IDataProvider() {};
/**
* The function is used by onevpl::GSource to extract binary data stream from @ref IDataProvider
* implementation.
*
* It MUST throw `DataProviderException` kind exceptions in fail cases.
* It MUST return 0 in EOF which considered as not-fail case.
*
* @param out_data_bytes_size the available capacity of out_data buffer.
* @param out_data the output consumer buffer with capacity out_data_bytes_size.
* @return fetched bytes count.
*/
virtual size_t fetch_data(size_t out_data_bytes_size, void* out_data) = 0;
/**
* The function is used by onevpl::GSource to check more binary data availability.
*
* It MUST return TRUE in case of EOF and NO_THROW exceptions.
*
* @return boolean value which detects end of stream
*/
virtual bool empty() const = 0;
};
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv
#endif // GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP

@ -1,44 +0,0 @@
// 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) 2021 Intel Corporation
#ifndef OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP
#define OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP
#include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/streaming/meta.hpp>
#include <opencv2/gapi/streaming/source.hpp>
namespace cv {
namespace gapi {
namespace wip {
class GAPI_EXPORTS OneVPLSource : public IStreamSource
{
public:
struct Priv;
explicit OneVPLSource(const std::string& filePath);
~OneVPLSource() override;
bool pull(cv::gapi::wip::Data& data) override;
GMetaArg descr_of() const override;
private:
explicit OneVPLSource(std::unique_ptr<Priv>&& impl);
std::unique_ptr<Priv> m_priv;
};
template<class... Args>
GAPI_EXPORTS_W cv::Ptr<IStreamSource> inline make_vpl_src(const std::string& filePath, Args&&... args)
{
return make_src<OneVPLSource>(filePath, std::forward<Args>(args)...);
}
} // namespace wip
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP

@ -0,0 +1,64 @@
// 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) 2021 Intel Corporation
#ifndef OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP
#define OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP
#include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/streaming/meta.hpp>
#include <opencv2/gapi/streaming/source.hpp>
#include <opencv2/gapi/streaming/onevpl/cfg_params.hpp>
#include <opencv2/gapi/streaming/onevpl/data_provider_interface.hpp>
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
using CfgParams = std::vector<CfgParam>;
/**
* @brief G-API streaming source based on OneVPL implementation.
*
* This class implements IStreamSource interface.
* Its constructor takes source file path (in usual way) or @ref onevpl::IDataProvider
* interface implementation (for not file-based sources). It also allows to pass-through
* oneVPL configuration parameters by using several @ref onevpl::CfgParam.
*
* @note stream sources are passed to G-API via shared pointers, so
* please gapi::make_onevpl_src<> to create objects and ptr() to pass a
* GSource to cv::gin().
*/
class GAPI_EXPORTS GSource : public IStreamSource
{
public:
struct Priv;
GSource(const std::string& filePath,
const CfgParams& cfg_params = CfgParams{});
GSource(std::shared_ptr<IDataProvider> source,
const CfgParams& cfg_params = CfgParams{});
~GSource() override;
bool pull(cv::gapi::wip::Data& data) override;
GMetaArg descr_of() const override;
private:
explicit GSource(std::unique_ptr<Priv>&& impl);
std::unique_ptr<Priv> m_priv;
};
} // namespace onevpl
template<class... Args>
GAPI_EXPORTS_W cv::Ptr<IStreamSource> inline make_onevpl_src(Args&&... args)
{
return make_src<onevpl::GSource>(std::forward<Args>(args)...);
}
} // namespace wip
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP

@ -9,7 +9,7 @@
#include <opencv2/gapi/cpu/gcpukernel.hpp> #include <opencv2/gapi/cpu/gcpukernel.hpp>
#include <opencv2/gapi/infer/ie.hpp> #include <opencv2/gapi/infer/ie.hpp>
#include <opencv2/gapi/render.hpp> #include <opencv2/gapi/render.hpp>
#include <opencv2/gapi/streaming/onevpl/onevpl_source.hpp> #include <opencv2/gapi/streaming/onevpl/source.hpp>
#include <opencv2/highgui.hpp> // CommandLineParser #include <opencv2/highgui.hpp> // CommandLineParser
const std::string about = const std::string about =
@ -19,7 +19,8 @@ const std::string keys =
"{ input | | Path to the input demultiplexed video file }" "{ input | | Path to the input demultiplexed video file }"
"{ output | | Path to the output RAW video file. Use .avi extension }" "{ output | | Path to the output RAW video file. Use .avi extension }"
"{ facem | face-detection-adas-0001.xml | Path to OpenVINO IE face detection model (.xml) }" "{ facem | face-detection-adas-0001.xml | Path to OpenVINO IE face detection model (.xml) }"
"{ faced | CPU | Target device for face detection model (e.g. CPU, GPU, VPU, ...) }"; "{ cfg_params | <prop name>:<value>;<prop name>:<value> | Semicolon separated list of oneVPL mfxVariants which is used for configuring source (see `MFXSetConfigFilterProperty` by https://spec.oneapi.io/versions/latest/elements/oneVPL/source/index.html) }";
namespace { namespace {
std::string get_weights_path(const std::string &model_path) { std::string get_weights_path(const std::string &model_path) {
@ -155,6 +156,10 @@ GAPI_OCV_KERNEL(OCVBBoxes, BBoxes) {
} // namespace custom } // namespace custom
namespace cfg {
typename cv::gapi::wip::onevpl::CfgParam create_from_string(const std::string &line);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
cv::CommandLineParser cmd(argc, argv, keys); cv::CommandLineParser cmd(argc, argv, keys);
@ -178,10 +183,22 @@ int main(int argc, char *argv[]) {
} }
} }
// get oneVPL cfg params from cmd
std::stringstream params_list(cmd.get<std::string>("cfg_params"));
std::vector<cv::gapi::wip::onevpl::CfgParam> source_cfgs;
try {
std::string line;
while (std::getline(params_list, line, ';')) {
source_cfgs.push_back(cfg::create_from_string(line));
}
} catch (const std::exception& ex) {
std::cerr << "Invalid cfg parameter: " << ex.what() << std::endl;
return -1;
}
auto face_net = cv::gapi::ie::Params<custom::FaceDetector> { auto face_net = cv::gapi::ie::Params<custom::FaceDetector> {
face_model_path, // path to topology IR face_model_path, // path to topology IR
get_weights_path(face_model_path), // path to weights get_weights_path(face_model_path) // path to weights
cmd.get<std::string>("faced"), // device specifier
}; };
auto kernels = cv::gapi::kernels auto kernels = cv::gapi::kernels
< custom::OCVLocateROI < custom::OCVLocateROI
@ -192,7 +209,7 @@ int main(int argc, char *argv[]) {
// Create source // Create source
cv::Ptr<cv::gapi::wip::IStreamSource> cap; cv::Ptr<cv::gapi::wip::IStreamSource> cap;
try { try {
cap = cv::gapi::wip::make_vpl_src(file_path); cap = cv::gapi::wip::make_onevpl_src(file_path, source_cfgs);
std::cout << "oneVPL source desription: " << cap->descr_of() << std::endl; std::cout << "oneVPL source desription: " << cap->descr_of() << std::endl;
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::cerr << "Cannot create source: " << ex.what() << std::endl; std::cerr << "Cannot create source: " << ex.what() << std::endl;
@ -213,7 +230,7 @@ int main(int argc, char *argv[]) {
cv::GStreamingCompiled pipeline; cv::GStreamingCompiled pipeline;
try { try {
pipeline = cv::GComputation(cv::GIn(in), cv::GOut(out)) pipeline = cv::GComputation(cv::GIn(in), cv::GOut(out))
.compileStreaming(cv::compile_args(kernels, networks)); .compileStreaming(cv::compile_args(kernels, networks));
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::cerr << "Exception occured during pipeline construction: " << ex.what() << std::endl; std::cerr << "Exception occured during pipeline construction: " << ex.what() << std::endl;
@ -252,3 +269,25 @@ int main(int argc, char *argv[]) {
return 0; return 0;
} }
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);
}
}

@ -0,0 +1,137 @@
// 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) 2021 Intel Corporation
#include <opencv2/gapi/util/throw.hpp>
#include <opencv2/gapi/streaming/onevpl/cfg_params.hpp>
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
namespace util {
struct variant_comparator : cv::util::static_visitor<bool, variant_comparator> {
variant_comparator(const CfgParam::value_t& rhs_value) :
rhs(rhs_value) {}
template<typename ValueType>
bool visit(const ValueType& lhs) const {
return lhs < cv::util::get<ValueType>(rhs);
}
private:
const CfgParam::value_t& rhs;
};
} // namespace util
struct CfgParam::Priv {
Priv(const std::string& param_name, CfgParam::value_t&& param_value, bool is_major_param) :
name(param_name), value(std::forward<value_t>(param_value)), major_flag(is_major_param) {
}
const CfgParam::name_t& get_name_impl() const {
return name;
}
const CfgParam::value_t& get_value_impl() const {
return value;
}
bool is_major_impl() const {
return major_flag;
}
// comparison implementation
bool operator< (const Priv& rhs) const {
// implement default pair comparison
if (get_name_impl() < rhs.get_name_impl()) {
return true;
} else if (get_name_impl() > rhs.get_name_impl()) {
return false;
}
//TODO implement operator < for cv::util::variant
const CfgParam::value_t& lvar = get_value_impl();
const CfgParam::value_t& rvar = rhs.get_value_impl();
if (lvar.index() < rvar.index()) {
return true;
} else if (lvar.index() > rvar.index()) {
return false;
}
util::variant_comparator comp(rvar);
return cv::util::visit(comp, lvar);
}
bool operator==(const Priv& rhs) const {
return (get_name_impl() == rhs.get_name_impl())
&& (get_value_impl() == rhs.get_value_impl());
}
bool operator!=(const Priv& rhs) const {
return !(*this == rhs);
}
CfgParam::name_t name;
CfgParam::value_t value;
bool major_flag;
};
CfgParam::CfgParam (const std::string& param_name, value_t&& param_value, bool is_major_param) :
m_priv(new Priv(param_name, std::move(param_value), is_major_param)) {
}
CfgParam::~CfgParam() = default;
CfgParam& CfgParam::operator=(const CfgParam& src) {
if (this != &src) {
m_priv = src.m_priv;
}
return *this;
}
CfgParam& CfgParam::operator=(CfgParam&& src) {
if (this != &src) {
m_priv = std::move(src.m_priv);
}
return *this;
}
CfgParam::CfgParam(const CfgParam& src) :
m_priv(src.m_priv) {
}
CfgParam::CfgParam(CfgParam&& src) :
m_priv(std::move(src.m_priv)) {
}
const CfgParam::name_t& CfgParam::get_name() const {
return m_priv->get_name_impl();
}
const CfgParam::value_t& CfgParam::get_value() const {
return m_priv->get_value_impl();
}
bool CfgParam::is_major() const {
return m_priv->is_major_impl();
}
bool CfgParam::operator< (const CfgParam& rhs) const {
return *m_priv < *rhs.m_priv;
}
bool CfgParam::operator==(const CfgParam& rhs) const {
return *m_priv == *rhs.m_priv;
}
bool CfgParam::operator!=(const CfgParam& rhs) const {
return *m_priv != *rhs.m_priv;
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

@ -0,0 +1,22 @@
#include <errno.h>
#include <string.h>
#include <opencv2/gapi/streaming/onevpl/data_provider_interface.hpp>
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
DataProviderSystemErrorException::DataProviderSystemErrorException(int error_code, const std::string& desription) {
reason = desription + ", error: " + std::to_string(error_code) + ", desctiption: " + strerror(error_code);
}
DataProviderSystemErrorException::~DataProviderSystemErrorException() = default;
const char* DataProviderSystemErrorException::what() const noexcept {
return reason.c_str();
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

@ -0,0 +1,47 @@
// 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) 2021 Intel Corporation
#include <errno.h>
#include "streaming/onevpl/file_data_provider.hpp"
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
FileDataProvider::FileDataProvider(const std::string& file_path) :
source_handle(fopen(file_path.c_str(), "rb"), &fclose) {
if (!source_handle) {
throw DataProviderSystemErrorException(errno,
"FileDataProvider: cannot open source file: " + file_path);
}
}
FileDataProvider::~FileDataProvider() = default;
size_t FileDataProvider::fetch_data(size_t out_data_bytes_size, void* out_data) {
if (empty()) {
return 0;
}
size_t ret = fread(out_data, 1, out_data_bytes_size, source_handle.get());
if (ret == 0) {
if (feof(source_handle.get())) {
source_handle.reset();
} else {
throw DataProviderSystemErrorException (errno, "FileDataProvider::fetch_data error read");
}
}
return ret;
}
bool FileDataProvider::empty() const {
return !source_handle;
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

@ -0,0 +1,33 @@
// 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) 2021 Intel Corporation
#ifndef GAPI_STREAMING_ONEVPL_ONEVPL_FILE_DATA_PROVIDER_HPP
#define GAPI_STREAMING_ONEVPL_ONEVPL_FILE_DATA_PROVIDER_HPP
#include <stdio.h>
#include <opencv2/gapi/streaming/onevpl/data_provider_interface.hpp>
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
struct FileDataProvider : public IDataProvider {
using file_ptr = std::unique_ptr<FILE, decltype(&fclose)>;
FileDataProvider(const std::string& file_path);
~FileDataProvider();
size_t fetch_data(size_t out_data_bytes_size, void* out_data) override;
bool empty() const override;
private:
file_ptr source_handle;
};
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv
#endif // GAPI_STREAMING_ONEVPL_ONEVPL_FILE_DATA_PROVIDER_HPP

@ -1,48 +0,0 @@
// 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) 2021 Intel Corporation
#include <opencv2/gapi/streaming/onevpl/onevpl_source.hpp>
#include "streaming/onevpl/onevpl_source_priv.hpp"
namespace cv {
namespace gapi {
namespace wip {
#ifdef HAVE_ONEVPL
OneVPLSource::OneVPLSource(const std::string& filePath) :
OneVPLSource(std::unique_ptr<Priv>(new OneVPLSource::Priv(filePath))) {
if (filePath.empty()) {
util::throw_error(std::logic_error("Cannot create 'OneVPLSource' on empty source file name"));
}
}
#else
OneVPLSource::OneVPLSource(const std::string&) {
GAPI_Assert(false && "Unsupported: G-API compiled without `WITH_GAPI_ONEVPL=ON`");
}
#endif
OneVPLSource::OneVPLSource(std::unique_ptr<Priv>&& impl) :
IStreamSource(),
m_priv(std::move(impl)) {
}
OneVPLSource::~OneVPLSource() {
}
bool OneVPLSource::pull(cv::gapi::wip::Data& data)
{
return m_priv->pull(data);
}
GMetaArg OneVPLSource::descr_of() const
{
return m_priv->descr_of();
}
} // namespace wip
} // namespace gapi
} // namespace cv

@ -0,0 +1,58 @@
// 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) 2021 Intel Corporation
#include <opencv2/gapi/streaming/onevpl/source.hpp>
#include "streaming/onevpl/source_priv.hpp"
#include "streaming/onevpl/file_data_provider.hpp"
namespace cv {
namespace gapi {
namespace wip {
namespace onevpl {
#ifdef HAVE_ONEVPL
GSource::GSource(const std::string& filePath, const CfgParams& cfg_params) :
GSource(std::unique_ptr<Priv>(new GSource::Priv(std::make_shared<FileDataProvider>(filePath),
cfg_params))) {
if (filePath.empty()) {
util::throw_error(std::logic_error("Cannot create 'GSource' on empty source file name"));
}
}
GSource::GSource(std::shared_ptr<IDataProvider> source, const CfgParams& cfg_params) :
GSource(std::unique_ptr<Priv>(new GSource::Priv(source, cfg_params))) {
}
#else
GSource::GSource(const std::string&, const CfgParams&) {
GAPI_Assert(false && "Unsupported: G-API compiled without `WITH_GAPI_ONEVPL=ON`");
}
GSource::GSource(std::shared_ptr<IDataProvider>, const CfgParams&) {
GAPI_Assert(false && "Unsupported: G-API compiled without `WITH_GAPI_ONEVPL=ON`");
}
#endif
GSource::GSource(std::unique_ptr<Priv>&& impl) :
IStreamSource(),
m_priv(std::move(impl)) {
}
GSource::~GSource() = default;
bool GSource::pull(cv::gapi::wip::Data& data)
{
return m_priv->pull(data);
}
GMetaArg GSource::descr_of() const
{
return m_priv->descr_of();
}
} // namespace onevpl
} // namespace wip
} // namespace gapi
} // namespace cv

@ -7,19 +7,21 @@
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
#include "streaming/onevpl/onevpl_source_priv.hpp" #include "streaming/onevpl/source_priv.hpp"
#include "logger.hpp" #include "logger.hpp"
#ifndef HAVE_ONEVPL #ifndef HAVE_ONEVPL
namespace cv { namespace cv {
namespace gapi { namespace gapi {
namespace wip { namespace wip {
bool OneVPLSource::Priv::pull(cv::gapi::wip::Data&) { namespace onevpl {
bool GSource::Priv::pull(cv::gapi::wip::Data&) {
return true; return true;
} }
GMetaArg OneVPLSource::Priv::descr_of() const { GMetaArg GSource::Priv::descr_of() const {
return {}; return {};
} }
} // namespace onevpl
} // namespace wip } // namespace wip
} // namespace gapi } // namespace gapi
} // namespace cv } // namespace cv
@ -29,33 +31,35 @@ GMetaArg OneVPLSource::Priv::descr_of() const {
namespace cv { namespace cv {
namespace gapi { namespace gapi {
namespace wip { namespace wip {
OneVPLSource::Priv::Priv() : namespace onevpl {
GSource::Priv::Priv() :
mfx_handle(MFXLoad()) mfx_handle(MFXLoad())
{ {
GAPI_LOG_INFO(nullptr, "Initialized MFX handle: " << mfx_handle); GAPI_LOG_INFO(nullptr, "Initialized MFX handle: " << mfx_handle);
description_is_valid = false; description_is_valid = false;
} }
OneVPLSource::Priv::Priv(const std::string&) : GSource::Priv::Priv(std::shared_ptr<IDataProvider>, const std::vector<CfgParam>&) :
OneVPLSource::Priv() GSource::Priv()
{ {
} }
OneVPLSource::Priv::~Priv() GSource::Priv::~Priv()
{ {
GAPI_LOG_INFO(nullptr, "Unload MFX handle: " << mfx_handle); GAPI_LOG_INFO(nullptr, "Unload MFX handle: " << mfx_handle);
MFXUnload(mfx_handle); MFXUnload(mfx_handle);
} }
bool OneVPLSource::Priv::pull(cv::gapi::wip::Data&) bool GSource::Priv::pull(cv::gapi::wip::Data&)
{ {
return false; return false;
} }
GMetaArg OneVPLSource::Priv::descr_of() const GMetaArg GSource::Priv::descr_of() const
{ {
return {}; return {};
} }
} // namespace onevpl
} // namespace wip } // namespace wip
} // namespace gapi } // namespace gapi
} // namespace cv } // namespace cv

@ -14,7 +14,7 @@
#include <opencv2/gapi/garg.hpp> #include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/streaming/meta.hpp> #include <opencv2/gapi/streaming/meta.hpp>
#include <opencv2/gapi/streaming/onevpl/onevpl_source.hpp> #include <opencv2/gapi/streaming/onevpl/source.hpp>
#ifdef HAVE_ONEVPL #ifdef HAVE_ONEVPL
#if (MFX_VERSION >= 2000) #if (MFX_VERSION >= 2000)
@ -28,10 +28,12 @@
namespace cv { namespace cv {
namespace gapi { namespace gapi {
namespace wip { namespace wip {
namespace onevpl {
struct OneVPLSource::Priv struct GSource::Priv
{ {
explicit Priv(const std::string& file_path); explicit Priv(std::shared_ptr<IDataProvider> provider,
const std::vector<CfgParam>& params);
~Priv(); ~Priv();
bool pull(cv::gapi::wip::Data& data); bool pull(cv::gapi::wip::Data& data);
@ -41,6 +43,7 @@ private:
mfxLoader mfx_handle; mfxLoader mfx_handle;
bool description_is_valid; bool description_is_valid;
}; };
} // namespace onevpl
} // namespace wip } // namespace wip
} // namespace gapi } // namespace gapi
} // namespace cv } // namespace cv
@ -50,11 +53,13 @@ private:
namespace cv { namespace cv {
namespace gapi { namespace gapi {
namespace wip { namespace wip {
struct OneVPLSource::Priv final namespace onevpl {
struct GSource::Priv final
{ {
bool pull(cv::gapi::wip::Data&); bool pull(cv::gapi::wip::Data&);
GMetaArg descr_of() const; GMetaArg descr_of() const;
}; };
} // namespace onevpl
} // namespace wip } // namespace wip
} // namespace gapi } // namespace gapi
} // namespace cv } // namespace cv

@ -25,6 +25,17 @@
#include <opencv2/gapi/streaming/desync.hpp> #include <opencv2/gapi/streaming/desync.hpp>
#include <opencv2/gapi/streaming/format.hpp> #include <opencv2/gapi/streaming/format.hpp>
#include <opencv2/gapi/streaming/onevpl/source.hpp>
#ifdef HAVE_ONEVPL
#if (MFX_VERSION >= 2000)
#include <vpl/mfxdispatcher.h>
#endif
#include <vpl/mfx.h>
#endif // HAVE_ONEVPL
namespace opencv_test namespace opencv_test
{ {
namespace namespace
@ -273,6 +284,22 @@ void checkPullOverload(const cv::Mat& ref,
EXPECT_EQ(0., cv::norm(ref, out_mat, cv::NORM_INF)); EXPECT_EQ(0., cv::norm(ref, out_mat, cv::NORM_INF));
} }
struct StreamDataProvider : public cv::gapi::wip::onevpl::IDataProvider {
StreamDataProvider(std::istream& in) : data_stream (in) {
EXPECT_TRUE(in);
}
size_t fetch_data(size_t out_data_size, void* out_data_buf) override {
data_stream.read(reinterpret_cast<char*>(out_data_buf), out_data_size);
return data_stream.gcount();
}
bool empty() const override {
return data_stream.eof() || data_stream.bad();
}
private:
std::istream& data_stream;
};
} // anonymous namespace } // anonymous namespace
TEST_P(GAPI_Streaming, SmokeTest_ConstInput_GMat) TEST_P(GAPI_Streaming, SmokeTest_ConstInput_GMat)
@ -2214,4 +2241,47 @@ TEST(GAPI_Streaming, TestPythonAPI)
cc.stop(); cc.stop();
} }
#ifdef HAVE_ONEVPL
const unsigned char hevc_header[] = {
0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0C, 0x06, 0xFF, 0xFF, 0x01, 0x40, 0x00,
0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0x00,
0x00, 0x04, 0x02, 0x10, 0x30, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03,
0x01, 0xE5, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x06, 0x01, 0x40, 0x00, 0x00,
0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0x00, 0x00,
0xA0, 0x10, 0x20, 0x61, 0x63, 0x41, 0x00, 0x86, 0x49, 0x1B, 0x2B, 0x20, 0x00,
0x00, 0x00, 0x01, 0x44, 0x01, 0xC0, 0x71, 0xC0, 0xD9, 0x20, 0x00, 0x00, 0x00,
0x01, 0x26, 0x01, 0xAF, 0x0C
};
TEST(OneVPL_Source, Init)
{
using CfgParam = cv::gapi::wip::onevpl::CfgParam;
std::vector<CfgParam> src_params;
src_params.push_back(CfgParam::create<uint32_t>("mfxImplDescription.Impl",
MFX_IMPL_TYPE_HARDWARE));
src_params.push_back(CfgParam::create<uint32_t>("mfxImplDescription.AccelerationMode",
MFX_ACCEL_MODE_VIA_D3D11, false));
src_params.push_back(CfgParam::create<uint32_t>("mfxImplDescription.mfxDecoderDescription.decoder.CodecID",
MFX_CODEC_HEVC));
std::stringstream stream(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
EXPECT_TRUE(stream.write(reinterpret_cast<char*>(const_cast<unsigned char *>(hevc_header)),
sizeof(hevc_header)));
std::shared_ptr<cv::gapi::wip::onevpl::IDataProvider> stream_data_provider = std::make_shared<StreamDataProvider>(stream);
cv::Ptr<cv::gapi::wip::IStreamSource> cap;
bool cap_created = false;
try {
cap = cv::gapi::wip::make_onevpl_src(stream_data_provider, src_params);
cap_created = true;
} catch (const std::exception&) {
}
ASSERT_TRUE(cap_created);
cv::gapi::wip::Data out;
while (cap->pull(out)) {
(void)out;
}
EXPECT_TRUE(stream_data_provider->empty());
}
#endif
} // namespace opencv_test } // namespace opencv_test

Loading…
Cancel
Save