unsigned int height {};
unsigned int byte_per_pixel {};
ImagePixelFormat pixel_format { ImagePixelFormat::NONE };
+ bool custom { false };
};
struct RawDataType : public BaseDataType {
INCLUDE(${ROOT_DIRECTORY}/input/CMakeLists.txt)
INCLUDE(${ROOT_DIRECTORY}/inference/CMakeLists.txt)
+INCLUDE(task_manager/CMakeLists.txt)
+
IF (${USE_AUTOZOOM_API})
INCLUDE(auto_zoom/CMakeLists.txt)
ENDIF()
--- /dev/null
+SET(SINGLEO_SERVICE_SOURCE_FILES
+ ${SINGLEO_SERVICE_SOURCE_FILES}
+ task_manager/src/TaskManager.cpp
+ task_manager/src/InferenceNode.cpp
+ task_manager/src/CallbackNode.cpp
+)
+
+LIST(APPEND SERVICE_HEADER_LIST ${SERVICE_HEADER_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/task_manager/include)
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CALLBACK_NODE_H__
+#define __CALLBACK_NODE_H__
+
+#include <mutex>
+#include <condition_variable>
+
+#include "INode.h"
+#include "SingleoException.h"
+
+namespace singleo
+{
+namespace services
+{
+class CallbackNode : public INode
+{
+private:
+ std::string _name;
+ NodeType _type { NodeType::CB };
+ std::vector<std::shared_ptr<INode> > _dependencies;
+ NodeCb _cb;
+ std::vector<std::shared_ptr<BaseDataType> > _inputs;
+ std::shared_ptr<BaseDataType> _output;
+ void *_user_data { nullptr };
+ bool _completed { false };
+ std::condition_variable _event;
+ std::mutex _mutex;
+
+public:
+ CallbackNode() = default;
+ virtual ~CallbackNode() = default;
+
+ NodeType getType() override;
+ void setName(std::string name) override
+ {
+ _name = name;
+ }
+ std::string &getName() override
+ {
+ return _name;
+ }
+ void addInput(std::shared_ptr<BaseDataType> input)
+ {
+ throw exception::InvalidOperation("Not supported.");
+ }
+ std::vector<std::shared_ptr<BaseDataType> > &getInputs() override;
+ void setInferenceService(std::unique_ptr<inference::IInferenceServiceInterface> &&service) override
+ {
+ throw exception::InvalidOperation("Not supported.");
+ }
+ inference::IInferenceServiceInterface *getInferenceService() override
+ {
+ throw exception::InvalidOperation("Not supported.");
+ }
+ void setCb(const NodeCb &cb, void *user_data) override;
+ NodeCb getCb() override;
+ void setUserData(void *user_data) override;
+ void *getUserData() override;
+ void addDependency(std::shared_ptr<INode> node) override;
+ std::vector<std::shared_ptr<INode> > &getDependencies() override;
+
+ void setOutput(std::shared_ptr<BaseDataType> output) override;
+ std::shared_ptr<BaseDataType> &getOutput() override;
+ void wait() override;
+ void wakeup() override;
+};
+
+}
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __INODE_H__
+#define __INODE_H__
+
+#include <vector>
+#include <memory>
+#include <functional>
+
+#include "SingleoCommonTypes.h"
+#include "ServiceDataType.h"
+#include "IInferenceServiceInterface.h"
+
+namespace singleo
+{
+namespace services
+{
+enum class NodeType { NONE, INFERENCE, CB };
+
+using NodeCb = std::function<void(void *user_data, std::vector<BaseResultType *> &results,
+ std::shared_ptr<BaseDataType> input)>;
+
+class INode
+{
+public:
+ virtual ~INode() {};
+
+ virtual NodeType getType() = 0;
+ virtual void setName(std::string name) = 0;
+ virtual std::string &getName() = 0;
+ virtual void addInput(std::shared_ptr<BaseDataType> input) = 0;
+ virtual std::vector<std::shared_ptr<BaseDataType> > &getInputs() = 0;
+ virtual void setInferenceService(std::unique_ptr<inference::IInferenceServiceInterface> &&service) = 0;
+ virtual inference::IInferenceServiceInterface *getInferenceService() = 0;
+ virtual void setCb(const NodeCb &cb, void *user_data) = 0;
+ virtual NodeCb getCb() = 0;
+ virtual void setUserData(void *user_data) = 0;
+ virtual void *getUserData() = 0;
+ virtual void addDependency(std::shared_ptr<INode> node) = 0;
+ virtual std::vector<std::shared_ptr<INode> > &getDependencies() = 0;
+ virtual void setOutput(std::shared_ptr<BaseDataType> output) = 0;
+ virtual std::shared_ptr<BaseDataType> &getOutput() = 0;
+ virtual void wait() = 0;
+ virtual void wakeup() = 0;
+};
+
+}
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __INFERENCE_NODE_H__
+#define __INFERENCE_NODE_H__
+
+#include <mutex>
+#include <condition_variable>
+
+#include "INode.h"
+#include "SingleoException.h"
+
+namespace singleo
+{
+namespace services
+{
+class InferenceNode : public INode
+{
+private:
+ NodeType _type { NodeType::INFERENCE };
+ std::string _name;
+ std::unique_ptr<inference::IInferenceServiceInterface> _service;
+ std::vector<std::shared_ptr<INode> > _dependencies;
+ std::vector<std::shared_ptr<BaseDataType> > _inputs;
+ std::shared_ptr<BaseDataType> _output;
+ bool _completed { false };
+ std::condition_variable _event;
+ std::mutex _mutex;
+
+public:
+ InferenceNode() = default;
+ virtual ~InferenceNode() = default;
+
+ NodeType getType() override;
+ void setName(std::string name) override
+ {
+ _name = name;
+ }
+ std::string &getName() override
+ {
+ return _name;
+ }
+ void addInput(std::shared_ptr<BaseDataType> input) override;
+ std::vector<std::shared_ptr<BaseDataType> > &getInputs() override;
+ void setInferenceService(std::unique_ptr<inference::IInferenceServiceInterface> &&service) override;
+ inference::IInferenceServiceInterface *getInferenceService() override;
+ void setCb(const NodeCb &cb, void *user_data) override
+ {
+ throw exception::InvalidOperation("Not supported.");
+ };
+ NodeCb getCb() override
+ {
+ throw exception::InvalidOperation("Not supported.");
+ };
+ void setUserData(void *user_data) override
+ {
+ throw exception::InvalidOperation("Not supported.");
+ };
+ void *getUserData() override
+ {
+ throw exception::InvalidOperation("Not supported.");
+ };
+ void addDependency(std::shared_ptr<INode> node) override;
+ std::vector<std::shared_ptr<INode> > &getDependencies() override;
+ void setOutput(std::shared_ptr<BaseDataType> output) override;
+ std::shared_ptr<BaseDataType> &getOutput() override;
+ void wait() override;
+ void wakeup() override;
+};
+
+}
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TASK_MANAGER_H__
+#define __TASK_MANAGER_H__
+
+#include <vector>
+#include <memory>
+#include <thread>
+
+#include "IInferenceServiceInterface.h"
+#include "SingleoCommonTypes.h"
+#include "INode.h"
+
+namespace singleo
+{
+namespace services
+{
+class TaskManager
+{
+private:
+ std::vector<std::shared_ptr<BaseDataType> > _inputs;
+ std::vector<std::shared_ptr<INode> > _nodes;
+ std::vector<std::shared_ptr<std::thread> > _threads;
+
+ void threadCb(std::shared_ptr<INode> &node);
+
+public:
+ TaskManager() = default;
+ ~TaskManager() = default;
+
+ void addInput(BaseDataType &input);
+ std::vector<std::shared_ptr<BaseDataType> > &getInputs();
+ void addNode(std::shared_ptr<INode> node);
+ void run();
+ BaseResultType &output();
+ void clear();
+};
+
+}
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstring>
+#include "CallbackNode.h"
+
+using namespace std;
+
+namespace singleo
+{
+namespace services
+{
+NodeType CallbackNode::getType()
+{
+ return _type;
+}
+
+vector<shared_ptr<BaseDataType> > &CallbackNode::getInputs()
+{
+ return _inputs;
+}
+
+void CallbackNode::setCb(const NodeCb &cb, void *user_data)
+{
+ _cb = cb;
+ _user_data = user_data;
+}
+
+NodeCb CallbackNode::getCb()
+{
+ return _cb;
+}
+
+void CallbackNode::setUserData(void *user_data)
+{
+ _user_data = user_data;
+}
+
+void *CallbackNode::getUserData()
+{
+ return _user_data;
+}
+
+void CallbackNode::addDependency(std::shared_ptr<INode> node)
+{
+ _dependencies.push_back(node);
+}
+
+std::vector<std::shared_ptr<INode> > &CallbackNode::getDependencies()
+{
+ return _dependencies;
+}
+
+void CallbackNode::setOutput(std::shared_ptr<BaseDataType> output)
+{
+ _output = dynamic_pointer_cast<ImageDataType>(output);
+}
+
+std::shared_ptr<BaseDataType> &CallbackNode::getOutput()
+{
+ return _output;
+}
+
+void CallbackNode::wait()
+{
+ unique_lock<mutex> lock(_mutex);
+
+ // If already completed then just return.
+ if (_completed)
+ return;
+
+ _event.wait(lock, [this] { return this->_completed; });
+}
+
+void CallbackNode::wakeup()
+{
+ unique_lock<mutex> lock(_mutex);
+
+ _completed = true;
+ _event.notify_all();
+}
+
+}
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InferenceNode.h"
+
+using namespace std;
+using namespace singleo::inference;
+
+namespace singleo
+{
+namespace services
+{
+NodeType InferenceNode::getType()
+{
+ return _type;
+}
+
+void InferenceNode::addInput(shared_ptr<BaseDataType> input)
+{
+ _inputs.push_back(input);
+}
+
+vector<shared_ptr<BaseDataType> > &InferenceNode::getInputs()
+{
+ return _inputs;
+}
+
+void InferenceNode::setInferenceService(unique_ptr<inference::IInferenceServiceInterface> &&service)
+{
+ _service = move(service);
+}
+
+IInferenceServiceInterface *InferenceNode::getInferenceService()
+{
+ return _service.get();
+}
+
+void InferenceNode::addDependency(std::shared_ptr<INode> node)
+{
+ _dependencies.push_back(node);
+}
+
+std::vector<std::shared_ptr<INode> > &InferenceNode::getDependencies()
+{
+ return _dependencies;
+}
+
+void InferenceNode::setOutput(std::shared_ptr<BaseDataType> output)
+{
+ _output = dynamic_pointer_cast<ImageDataType>(output);
+}
+
+std::shared_ptr<BaseDataType> &InferenceNode::getOutput()
+{
+ return _output;
+}
+
+void InferenceNode::wait()
+{
+ unique_lock<mutex> lock(_mutex);
+
+ // If already completed then just return.
+ if (_completed)
+ return;
+
+ _event.wait(lock, [this] { return this->_completed; });
+}
+
+void InferenceNode::wakeup()
+{
+ unique_lock<mutex> lock(_mutex);
+
+ _completed = true;
+ _event.notify_all();
+}
+
+}
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstring>
+#include "SingleoException.h"
+#include "SingleoLog.h"
+#include "TaskManager.h"
+
+using namespace std;
+using namespace singleo::exception;
+
+namespace singleo
+{
+namespace services
+{
+void TaskManager::threadCb(shared_ptr<INode> &node)
+{
+ vector<BaseResultType *> results;
+ vector<shared_ptr<INode> > &dependencies = node->getDependencies();
+
+ SINGLEO_LOGD("Launched node name = %s", node->getName().c_str());
+
+ for (auto &n : dependencies) {
+ // Add the result if dependency node is inference service not callback.
+ if (n->getType() == NodeType::INFERENCE)
+ results.push_back(&n->getInferenceService()->result());
+ }
+
+ if (node->getType() == NodeType::INFERENCE) {
+ if (_inputs[0]->_data_type != DataType::IMAGE) {
+ SINGLEO_LOGE("Invalid input data type.");
+ throw InvalidOperation("Invalid input data type");
+ }
+
+ shared_ptr<ImageDataType> input;
+
+ // If no dependency then use input of current node as input source.
+ // Ps. In case of inference node, one of both - input from task manager
+ // (inference_node_a or inference_node_b) or input from dependency node
+ // output(inference_node_c) - will be used as input source like below graph,
+ //
+ // inference_node_a -----
+ // |------ Callback_node ------- inference_node_c
+ // inference_node_b -----
+ if (node->getDependencies().empty())
+ // TODO. consider for multiple inputs later.
+ input = dynamic_pointer_cast<ImageDataType>(node->getInputs()[0]);
+ else // Else if dependency then use output of dependency node(callback node).
+ input = dynamic_pointer_cast<ImageDataType>(node->getDependencies()[0]->getOutput());
+
+ node->getInferenceService()->invoke(*input);
+
+ // Inference request has been completed so release input data if the data was internally allocated by callback node.
+ if (input->custom)
+ delete input->ptr;
+
+ // Service request to 'input' has been completed so clean up it.
+ node->getInputs().clear();
+ } else if (node->getType() == NodeType::CB) {
+ NodeCb cb = node->getCb();
+ void *user_data = node->getUserData();
+
+ // Call the callback function registered in this callback node.
+ // In this callback, new data should be set by calling node->setOutput()
+ // if new data is made. TODO. consider for multiple inputs later.
+ cb(user_data, results, _inputs[0]);
+ }
+
+ // Wake up.
+ node->wakeup();
+}
+
+void TaskManager::addInput(BaseDataType &input)
+{
+ auto imageData = dynamic_cast<ImageDataType &>(input);
+
+ _inputs.push_back(make_shared<ImageDataType>(imageData));
+}
+
+vector<shared_ptr<BaseDataType> > &TaskManager::getInputs()
+{
+ return _inputs;
+}
+
+void TaskManager::addNode(std::shared_ptr<INode> node)
+{
+ _nodes.push_back(node);
+
+ // Initialize inference service.
+ if (node->getType() == NodeType::INFERENCE) {
+ node->getInferenceService()->configure();
+ node->getInferenceService()->prepare();
+ }
+}
+
+void TaskManager::run()
+{
+ if (_inputs.empty()) {
+ SINGLEO_LOGE("No input source.");
+ throw InvalidOperation("No input source.");
+ }
+
+ for (auto &n : _nodes) {
+ // Set input as source of current node.
+ // If no dependency then this node has to receive input source
+ // from singleo concrete service such as Autozoom, else if dependency
+ // then the input of the node will be set in threadCb callback function.
+ if (n->getDependencies().empty()) {
+ if (n->getType() != NodeType::INFERENCE) {
+ SINGLEO_LOGE("root node should be inference node.");
+ throw InvalidOperation("root node should be inference node.");
+ }
+
+ // TODO. consider for multiple sources later.
+ n->addInput(_inputs[0]);
+ }
+
+ vector<shared_ptr<INode> > &dependencies = n->getDependencies();
+
+ // Wait until all nodes added to this node as dependency are completed
+ for (auto &d : dependencies)
+ d->wait();
+
+ _threads.push_back(make_shared<thread>(&TaskManager::threadCb, this, std::ref(n)));
+ }
+
+ for (auto &t : _threads)
+ t->join();
+
+ _inputs.clear();
+ _threads.clear();
+}
+
+BaseResultType &TaskManager::output()
+{
+ auto service = _nodes[_nodes.size() - 1]->getInferenceService();
+
+ return service->result();
+}
+
+void TaskManager::clear()
+{
+ _nodes.clear();
+}
+
+}
+}
\ No newline at end of file