[ML][Pipeline] Implement getNodeInfo 06/251306/5
authorLukasz Bardeli <l.bardeli@samsung.com>
Tue, 12 Jan 2021 09:24:45 +0000 (10:24 +0100)
committerLukasz Bardeli <l.bardeli@samsung.com>
Mon, 18 Jan 2021 20:19:11 +0000 (21:19 +0100)
ACR: TWDAPI-274

[Verification] Code compiles without error. Tested in chrome console

var pipeline = tizen.ml.pipeline.createPipeline("videotestsrc ! video/x-raw,format=RGB,width=640,height=480 ! videorate max-rate=1 ! tensor_converter ! tensor_mux ! tensor_demux name=demux ! tensor_sink")
var nodeinfo = pipeline.getNodeInfo("demux")

Change-Id: I503f0a2a52b151ac676a64e2ad888f45abc51170
Signed-off-by: Lukasz Bardeli <l.bardeli@samsung.com>
src/ml/js/ml_pipeline.js
src/ml/ml.gyp
src/ml/ml_instance.cc
src/ml/ml_instance.h
src/ml/ml_pipeline.cc
src/ml/ml_pipeline.h
src/ml/ml_pipeline_manager.cc
src/ml/ml_pipeline_manager.h
src/ml/ml_pipeline_nodeinfo.cc [new file with mode: 0644]
src/ml/ml_pipeline_nodeinfo.h [new file with mode: 0644]

index 17dba5ef5d2de947939885843dcb2fd4449bb3d4..df2913afe62661f922ef3d2c382dec073eafd7cc 100755 (executable)
@@ -114,7 +114,11 @@ var Pipeline = function(id) {
 //Pipeline::state end
 
 //Pipeline::start() begin
-var ValidPipelineStartStopExceptions = ['NotFoundError', 'NotSupportedError', 'AbortError'];
+var ValidPipelineStartStopExceptions = [
+    'NotFoundError',
+    'NotSupportedError',
+    'AbortError'
+];
 Pipeline.prototype.start = function() {
     var nativeArgs = {
         id: this._id
@@ -163,7 +167,44 @@ Pipeline.prototype.dispose = function() {
 //Pipeline::dispose() end
 
 //Pipeline::getNodeInfo() begin
+var NodeInfo = function(name, pipeline_id) {
+    Object.defineProperties(this, {
+        name: { enumerable: true, writable: false, value: name },
+        _pipeline_id: { value: pipeline_id }
+    });
+};
+
+var ValidPipelineGetNodeInfoExceptions = [
+    'InvalidValuesError',
+    'NotFoundError',
+    'NotSupportedError',
+    'AbortError'
+];
+
+Pipeline.prototype.getNodeInfo = function() {
+    var args = validator_.validateArgs(arguments, [
+        {
+            name: 'name',
+            type: validator_.Types.STRING
+        }
+    ]);
+
+    var nativeArgs = {
+        id: this._id,
+        name: args.name
+    };
+
+    var result = native_.callSync('MLPipelineGetNodeInfo', nativeArgs);
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObjectAndValidate(
+            result,
+            ValidPipelineGetNodeInfoExceptions,
+            AbortError
+        );
+    }
 
+    return new NodeInfo(args.name, this._id);
+};
 //Pipeline::getNodeInfo() end
 
 //Pipeline::getSource() begin
index 65a987d23b70828e84ad94cf5862cdd0530126c8..c0ab82627fb86d65871c772e3cf488a2a00f69fa 100644 (file)
@@ -19,6 +19,8 @@
         'ml_pipeline.h',
         'ml_pipeline_manager.cc',
         'ml_pipeline_manager.h',
+        'ml_pipeline_nodeinfo.cc',
+        'ml_pipeline_nodeinfo.h',
         'ml_utils.cc',
         'ml_utils.h',
       ],
index 3a0cd4d4c91301d7a3e78c21abda3927bfcde147..7a69c2b6ef8b8c6c23ee88889c430b44ec56ab4c 100644 (file)
@@ -44,6 +44,7 @@ MlInstance::MlInstance() : pipeline_manager_{this} {
   REGISTER_METHOD(MLPipelineDispose);
   REGISTER_METHOD(MLPipelineStart);
   REGISTER_METHOD(MLPipelineStop);
+  REGISTER_METHOD(MLPipelineGetNodeInfo);
 // Pipeline API end
 
 #undef REGISTER_METHOD
@@ -66,6 +67,7 @@ MlInstance::~MlInstance() {
 namespace {
 
 const std::string kId = "id";
+const std::string kName = "name";
 const std::string kDefinition = "definition";
 const std::string kPipelineStateChangeListenerName = "listenerName";
 
@@ -205,7 +207,33 @@ void MlInstance::MLPipelineDispose(const picojson::value& args, picojson::object
 // Pipeline::dispose() end
 
 // Pipeline::getNodeInfo() begin
+void MlInstance::MLPipelineGetNodeInfo(const picojson::value& args, picojson::object& out) {
+  ScopeLogger("args: %s", args.serialize().c_str());
+
+  if (!args.get(kId).is<double>()) {
+    LoggerD("id is not a number");
+    ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Invalid pipeline"}, &out);
+    return;
+  }
+
+  if (!args.get(kName).is<std::string>()) {
+    LoggerD("name is not a string");
+    ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Invalid name"}, &out);
+    return;
+  }
 
+  auto name = args.get(kName).get<std::string>();
+  auto id = static_cast<int>(args.get(kId).get<double>());
+
+  PlatformResult result = pipeline_manager_.GetNodeInfo(id, name);
+
+  if (!result) {
+    LogAndReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
 // Pipeline::getNodeInfo() end
 
 // Pipeline::getSource() begin
index df6e214cd2dd9a2c54f09ad15e6a5b1f72cc455c..9b1f430c6104b7944ac7802f3830bc3328eb6724 100644 (file)
@@ -64,7 +64,7 @@ class MlInstance : public common::ParsedInstance {
   // Pipeline::dispose() end
 
   // Pipeline::getNodeInfo() begin
-
+  void MLPipelineGetNodeInfo(const picojson::value& args, picojson::object& out);
   // Pipeline::getNodeInfo() end
 
   // Pipeline::getSource() begin
index 10930cf24725802330d62f458ba55eb99aff8b1d..c843df35dab4d08aabe8fb44e6c4001c0ab2b306 100644 (file)
@@ -191,6 +191,8 @@ PlatformResult Pipeline::Dispose() {
    * If they're released after pipeline_, the app may crash.
    */
 
+  node_info_.clear();
+
   auto ret = ml_pipeline_destroy(pipeline_);
   if (ML_ERROR_NONE != ret) {
     LoggerE("ml_pipeline_destroy() failed: [%d] (%s)", ret, get_error_message(ret));
@@ -205,7 +207,26 @@ PlatformResult Pipeline::Dispose() {
 // Pipeline::dispose() end
 
 // Pipeline::getNodeInfo() begin
+PlatformResult Pipeline::GetNodeInfo(std::string& name) {
+  ScopeLogger("id_: [%d], name: [%s]", id_, name.c_str());
+
+  auto nodeinfo_it = node_info_.find(name);
+  if (node_info_.end() != nodeinfo_it) {
+    LoggerD("NodeInfo [%s] found", name.c_str());
+    return PlatformResult{};
+  }
 
+  std::unique_ptr<NodeInfo> node_info_ptr;
+  auto ret = NodeInfo::CreateNodeInfo(pipeline_, name, &node_info_ptr);
+
+  if (!ret) {
+    return ret;
+  }
+
+  node_info_.insert({name, std::move(node_info_ptr)});
+
+  return PlatformResult{};
+}
 // Pipeline::getNodeInfo() end
 
 // Pipeline::getSource() begin
index 42287f8bfb09c2e240707d320936dcf19a38a895..80c859baf09d222e53bd1843c4032b89e9ac3c1c 100644 (file)
 #include "common/extension.h"
 #include "common/picojson.h"
 #include "common/platform_result.h"
+#include "ml_pipeline_nodeinfo.h"
 
 using common::PlatformResult;
+using extension::ml::pipeline::NodeInfo;
 
 namespace extension {
 namespace ml {
@@ -68,7 +70,7 @@ class Pipeline {
   // Pipeline::dispose() end
 
   // Pipeline::getNodeInfo() begin
-
+  PlatformResult GetNodeInfo(std::string& name);
   // Pipeline::getNodeInfo() end
 
   // Pipeline::getSource() begin
@@ -135,6 +137,8 @@ class Pipeline {
   const std::string state_change_listener_name_;
   common::Instance* instance_ptr_;
 
+  std::map<std::string, std::unique_ptr<NodeInfo>> node_info_;
+
   static void PipelineStateChangeListener(ml_pipeline_state_e state, void* user_data);
 };
 
index 3d578618d9d72bf500f3021d215dbc62dfc96cf1..cadb4d4f58366db50cdda659d20f40692c321a97 100644 (file)
@@ -128,7 +128,18 @@ PlatformResult PipelineManager::DisposePipeline(int id) {
 // Pipeline::dispose() end
 
 // Pipeline::getNodeInfo() begin
+PlatformResult PipelineManager::GetNodeInfo(int id, std::string& name) {
+  ScopeLogger("id: [%d], name [%s]", id, name.c_str());
 
+  auto pipeline_it = pipelines_.find(id);
+  if (pipelines_.end() == pipeline_it) {
+    LoggerD("Pipeline not found: [%d]", id);
+    return PlatformResult{ErrorCode::NOT_FOUND_ERR, "Pipeline not found"};
+  }
+
+  auto ret = pipeline_it->second->GetNodeInfo(name);
+  return ret;
+}
 // Pipeline::getNodeInfo() end
 
 // Pipeline::getSource() begin
index 300aa311e679e63f987d233e03744c8ccf98d66e..63ee5aa79192514fe398b71dd2418f7f3ab4f51b 100644 (file)
@@ -60,7 +60,7 @@ class PipelineManager {
   // Pipeline::dispose() end
 
   // Pipeline::getNodeInfo() begin
-
+  PlatformResult GetNodeInfo(int id, std::string& name);
   // Pipeline::getNodeInfo() end
 
   // Pipeline::getSource() begin
diff --git a/src/ml/ml_pipeline_nodeinfo.cc b/src/ml/ml_pipeline_nodeinfo.cc
new file mode 100644 (file)
index 0000000..c1e7a34
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020 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 <tizen.h>
+
+#include "common/logger.h"
+#include "ml_pipeline_nodeinfo.h"
+#include "ml_utils.h"
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+namespace extension {
+namespace ml {
+namespace pipeline {
+
+PlatformResult NodeInfo::CreateNodeInfo(ml_pipeline_h pipeline, const std::string& name,
+                                        std::unique_ptr<NodeInfo>* out) {
+  std::unique_ptr<NodeInfo> nodeinfo_ptr{new (std::nothrow) NodeInfo{name}};
+  if (!nodeinfo_ptr) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "An unknown occurred.",
+                              ("Could not allocate memory for NodeInfo"));
+  }
+  auto ret = ml_pipeline_element_get_handle(pipeline, name.c_str(), &nodeinfo_ptr->node_info_);
+  if (ML_ERROR_NONE != ret) {
+    LoggerE("ml_pipeline_element_get_handle() failed: [%d] (%s)", ret, get_error_message(ret));
+    return util::ToPlatformResult(ret, "Could not get NodeInfo");
+  }
+
+  *out = std::move(nodeinfo_ptr);
+  return PlatformResult{};
+}
+
+NodeInfo::NodeInfo(const std::string& name) : name_{name} {
+  ScopeLogger("name: [%s], ", name.c_str());
+}
+
+NodeInfo::~NodeInfo() {
+  ScopeLogger("name: [%s], handle: [%p]", name_.c_str(), node_info_);
+
+  auto ret =  ml_pipeline_element_release_handle(node_info_);
+  if (ML_ERROR_NONE != ret) {
+    LoggerE("ml_pipeline_element_release_handle() failed: [%d] (%s)", ret, get_error_message(ret));
+  } else {
+    LoggerD("ml_pipeline_element_release_handle() succeeded");
+  }
+}
+
+}  // namespace pipeline
+}  // namespace ml
+}  // namespace extension
\ No newline at end of file
diff --git a/src/ml/ml_pipeline_nodeinfo.h b/src/ml/ml_pipeline_nodeinfo.h
new file mode 100644 (file)
index 0000000..4140025
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020 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 ML_ML_PIPELINE_NODEINFO_H_
+#define ML_ML_PIPELINE_NODEINFO_H_
+
+#include <memory>
+#include <string>
+
+#include <nnstreamer/nnstreamer.h>
+
+#include "common/platform_result.h"
+
+using common::PlatformResult;
+
+namespace extension {
+namespace ml {
+namespace pipeline {
+
+class NodeInfo {
+ public:
+  NodeInfo() = delete;
+  NodeInfo(const NodeInfo&) = delete;
+  NodeInfo& operator=(const NodeInfo&) = delete;
+  static PlatformResult CreateNodeInfo(ml_pipeline_h pipeline, const std::string& name,
+                                       std::unique_ptr<NodeInfo>* out);
+
+  ~NodeInfo();
+
+ private:
+  NodeInfo(const std::string& name);
+  const std::string name_;
+  ml_pipeline_element_h node_info_;
+};
+
+}  // namespace pipeline
+}  // namespace ml
+}  // namespace extension
+
+#endif  // ML_ML_PIPELINE_NODEINFO_H_
\ No newline at end of file