Merge pull request #18793 from dmatveev:dm/in_graph_metadata

G-API: Introduce runtime in-graph metadata

* G-API: In-graph metadata -- initial implementation

* G-API: Finish the in-graph metadata implementation for Streaming

* G-API: Fix standalone build & warnings for in-graph metadata

* G-API: In-graph meta -- fixed review comments

* G-API: Fix issues with desync causing failing tests
This commit is contained in:
Dmitry Matveev
2020-11-17 17:04:19 +03:00
committed by GitHub
parent b5c162175b
commit b866d0dc38
16 changed files with 681 additions and 55 deletions
+63 -4
View File
@@ -9,12 +9,14 @@
#define OPENCV_GAPI_GARG_HPP
#include <vector>
#include <unordered_map>
#include <type_traits>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/own/mat.hpp>
#include <opencv2/gapi/media.hpp>
#include <opencv2/gapi/util/util.hpp>
#include <opencv2/gapi/util/any.hpp>
#include <opencv2/gapi/util/variant.hpp>
@@ -93,7 +95,7 @@ using GArgs = std::vector<GArg>;
// FIXME: Express as M<GProtoArg...>::type
// FIXME: Move to a separate file!
using GRunArg = util::variant<
using GRunArgBase = util::variant<
#if !defined(GAPI_STANDALONE)
cv::UMat,
#endif // !defined(GAPI_STANDALONE)
@@ -105,6 +107,61 @@ using GRunArg = util::variant<
cv::detail::OpaqueRef,
cv::MediaFrame
>;
namespace detail {
template<typename,typename>
struct in_variant;
template<typename T, typename... Types>
struct in_variant<T, util::variant<Types...> >
: std::integral_constant<bool, cv::detail::contains<T, Types...>::value > {
};
} // namespace detail
struct GAPI_EXPORTS GRunArg: public GRunArgBase
{
// Metadata information here
using Meta = std::unordered_map<std::string, util::any>;
Meta meta;
// Mimic the old GRunArg semantics here, old of the times when
// GRunArg was an alias to variant<>
GRunArg();
GRunArg(const cv::GRunArg &arg);
GRunArg(cv::GRunArg &&arg);
GRunArg& operator= (const GRunArg &arg);
GRunArg& operator= (GRunArg &&arg);
template <typename T>
GRunArg(const T &t,
const Meta &m = Meta{},
typename std::enable_if< detail::in_variant<T, GRunArgBase>::value, int>::type = 0)
: GRunArgBase(t)
, meta(m)
{
}
template <typename T>
GRunArg(T &&t,
const Meta &m = Meta{},
typename std::enable_if< detail::in_variant<T, GRunArgBase>::value, int>::type = 0)
: GRunArgBase(std::move(t))
, meta(m)
{
}
template <typename T> auto operator= (const T &t)
-> typename std::enable_if< detail::in_variant<T, GRunArgBase>::value, cv::GRunArg>::type&
{
GRunArgBase::operator=(t);
return *this;
}
template <typename T> auto operator= (T&& t)
-> typename std::enable_if< detail::in_variant<T, GRunArgBase>::value, cv::GRunArg>::type&
{
GRunArgBase::operator=(std::move(t));
return *this;
}
};
using GRunArgs = std::vector<GRunArg>;
// TODO: Think about the addition operator
@@ -129,11 +186,13 @@ namespace gapi
namespace wip
{
/**
* @brief This aggregate type represents all types which G-API can handle (via variant).
* @brief This aggregate type represents all types which G-API can
* handle (via variant).
*
* It only exists to overcome C++ language limitations (where a `using`-defined class can't be forward-declared).
* It only exists to overcome C++ language limitations (where a
* `using`-defined class can't be forward-declared).
*/
struct Data: public GRunArg
struct GAPI_EXPORTS Data: public GRunArg
{
using GRunArg::GRunArg;
template <typename T>
@@ -15,6 +15,7 @@
#include <opencv2/gapi/own/exports.hpp>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/any.hpp>
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/util/throw.hpp>
#include <opencv2/gapi/util/type_traits.hpp>
@@ -119,6 +120,7 @@ namespace detail
virtual void mov(BasicOpaqueRef &ref) = 0;
virtual const void* ptr() const = 0;
virtual void set(const cv::util::any &a) = 0;
};
template<typename T> class OpaqueRefT final: public BasicOpaqueRef
@@ -212,6 +214,10 @@ namespace detail
}
virtual const void* ptr() const override { return &rref(); }
virtual void set(const cv::util::any &a) override {
wref() = util::any_cast<T>(a);
}
};
// This class strips type information from OpaqueRefT<> and makes it usable
@@ -285,6 +291,13 @@ namespace detail
// May be used to uniquely identify this object internally
const void *ptr() const { return m_ref->ptr(); }
// Introduced for in-graph meta handling
OpaqueRef& operator= (const cv::util::any &a)
{
m_ref->set(a);
return *this;
}
};
} // namespace detail
@@ -21,9 +21,11 @@
* Note for developers: please don't put videoio dependency in G-API
* because of this file.
*/
#include <chrono>
#include <opencv2/videoio.hpp>
#include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/streaming/meta.hpp>
namespace cv {
namespace gapi {
@@ -55,6 +57,7 @@ protected:
cv::VideoCapture cap;
cv::Mat first;
bool first_pulled = false;
int64_t counter = 0;
void prep()
{
@@ -80,19 +83,26 @@ protected:
GAPI_Assert(!first.empty());
first_pulled = true;
data = first; // no need to clone here since it was cloned already
return true;
}
if (!cap.isOpened()) return false;
cv::Mat frame;
if (!cap.read(frame))
else
{
// end-of-stream happened
return false;
if (!cap.isOpened()) return false;
cv::Mat frame;
if (!cap.read(frame))
{
// end-of-stream happened
return false;
}
// Same reason to clone as in prep()
data = frame.clone();
}
// Same reason to clone as in prep()
data = frame.clone();
// Tag data with seq_id/ts
const auto now = std::chrono::system_clock::now();
const auto dur = std::chrono::duration_cast<std::chrono::microseconds>
(now.time_since_epoch());
data.meta[cv::gapi::streaming::meta_tag::timestamp] = int64_t{dur.count()};
data.meta[cv::gapi::streaming::meta_tag::seq_id] = int64_t{counter++};
return true;
}
@@ -0,0 +1,79 @@
// 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) 2020 Intel Corporation
#ifndef OPENCV_GAPI_GSTREAMING_META_HPP
#define OPENCV_GAPI_GSTREAMING_META_HPP
#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/gcall.hpp>
#include <opencv2/gapi/gkernel.hpp>
#include <opencv2/gapi/gtype_traits.hpp>
namespace cv {
namespace gapi {
namespace streaming {
// FIXME: the name is debatable
namespace meta_tag {
static constexpr const char * timestamp = "org.opencv.gapi.meta.timestamp";
static constexpr const char * seq_id = "org.opencv.gapi.meta.seq_id";
} // namespace meta_tag
namespace detail {
struct GMeta {
static const char *id() {
return "org.opencv.streaming.meta";
}
// A universal yield for meta(), same as in GDesync
template<typename... R, int... IIs>
static std::tuple<R...> yield(cv::GCall &call, cv::detail::Seq<IIs...>) {
return std::make_tuple(cv::detail::Yield<R>::yield(call, IIs)...);
}
// Also a universal outMeta stub here
static GMetaArgs getOutMeta(const GMetaArgs &args, const GArgs &) {
return args;
}
};
} // namespace detail
template<typename T, typename G>
cv::GOpaque<T> meta(G g, const std::string &tag) {
using O = cv::GOpaque<T>;
cv::GKernel k{
detail::GMeta::id() // kernel id
, tag // kernel tag. Use meta tag here
, &detail::GMeta::getOutMeta // outMeta callback
, {cv::detail::GTypeTraits<O>::shape} // output Shape
, {cv::detail::GTypeTraits<G>::op_kind} // input data kinds
, {cv::detail::GObtainCtor<O>::get()} // output template ctors
};
cv::GCall call(std::move(k));
call.pass(g);
return std::get<0>(detail::GMeta::yield<O>(call, cv::detail::MkSeq<1>::type()));
}
template<typename G>
cv::GOpaque<int64_t> timestamp(G g) {
return meta<int64_t>(g, meta_tag::timestamp);
}
template<typename G>
cv::GOpaque<int64_t> seq_id(G g) {
return meta<int64_t>(g, meta_tag::seq_id);
}
template<typename G>
cv::GOpaque<int64_t> seqNo(G g) {
// Old name, compatibility only
return seq_id(g);
}
} // namespace streaming
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_GSTREAMING_META_HPP