From: Piotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics Date: Wed, 20 Jan 2021 10:55:36 +0000 (+0100) Subject: [ML][Single] Added manager file and implementation for openModel() X-Git-Tag: submit/tizen/20210128.113801~7^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F93%2F251893%2F7;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [ML][Single] Added manager file and implementation for openModel() [ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-273 [Verification] Code compiles without errors. Checked in chrome console with few calls: Success calls: tizen.ml.single.openModel("documents/mobilenet_v1_1.0_224_quant.tflite") tizen.ml.single.openModel("documents/mobilenet_v1_1.0_224_quant.tflite", null, null, "TENSORFLOW_LITE") tizen.ml.single.openModel("documents/mobilenet_v1_1.0_224_quant.tflite", null, null, "TENSORFLOW_LITE", "ANY", true) Fail for invalid or not-existing file: tizen.ml.single.openModel("documents/fail.tflite") // Abort Error tizen.ml.single.openModel("documents/notexisting") // NotFound tizen.ml.single.openModel("notexisting") // NotFound Change-Id: I8b2b89e60d8f265185d3ddcafcc224f4e5c15fa1 --- diff --git a/src/ml/js/ml_single.js b/src/ml/js/ml_single.js index f9aa0d82..22cf5ba9 100755 --- a/src/ml/js/ml_single.js +++ b/src/ml/js/ml_single.js @@ -17,12 +17,91 @@ var MachineLearningSingle = function() {}; // MachineLearningSingle::openModel() +var ValidOpenModelExceptions = [ + 'InvalidValuesError', + 'NotFoundError', + 'NotSupportedError', + 'SecurityError', + 'AbortError' +]; + +var NO_ID = -1; +MachineLearningSingle.prototype.openModel = function() { + var args = validator_.validateArgs(arguments, [ + { + name: 'modelPath', + type: types_.STRING + }, + { + name: 'inTensorsInfo', + type: types_.PLATFORM_OBJECT, + values: TensorsInfo, + optional: true, + nullable: true + }, + { + name: 'outTensorsInfo', + type: types_.PLATFORM_OBJECT, + values: TensorsInfo, + optional: true, + nullable: true + }, + { + name: 'fwType', + type: types_.ENUM, + values: Object.keys(NNFWType), + optional: true + }, + { + name: 'hwType', + type: types_.ENUM, + values: Object.keys(HWType), + optional: true + }, + { + name: 'isDynamicMode', + type: types_.BOOLEAN, + optional: true + } + ]); + try { + // get normalized URI of a file + args.modelPath = tizen.filesystem.toURI(args.modelPath); + } catch (e) { + throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Path is invalid'); + } + + var nativeArgs = { + modelPath: args.modelPath, + inTensorsInfo: args.inTensorsInfo ? args.inTensorsInfo._id : NO_ID, + outTensorsInfo: args.outTensorsInfo ? args.outTensorsInfo._id : NO_ID, + fwType: args.fwType ? args.fwType : 'ANY', + hwType: args.hwType ? args.hwType : 'ANY', + isDynamicMode: args.isDynamicMode ? args.isDynamicMode : false + }; + + var result = native_.callSync('MLSingleManagerOpenModel', nativeArgs); + if (native_.isFailure(result)) { + throw native_.getErrorObjectAndValidate( + result, + ValidOpenModelExceptions, + AbortError + ); + } + + return new SingleShot(result.id); +}; // MachineLearningSingle::openModelAsync() // OpenModelSuccessCallback // SingleShot interface (input & output) +var SingleShot = function(id) { + Object.defineProperties(this, { + _id: { value: id, writable: false, enumerable: false } + }); +}; // SingleShot::invoke() diff --git a/src/ml/ml.gyp b/src/ml/ml.gyp index a8fb82f2..62490a50 100644 --- a/src/ml/ml.gyp +++ b/src/ml/ml.gyp @@ -27,8 +27,10 @@ #TODO pipeline Valve 'ml_tensors_info_manager.cc', 'ml_tensors_info_manager.h', - #TODO single SingleShotManager - #TODO single SingleShot + 'ml_single_manager.cc', + 'ml_single_manager.h', + 'ml_singleshot.cc', + 'ml_singleshot.h', 'ml_utils.cc', 'ml_utils.h', ], diff --git a/src/ml/ml_instance.cc b/src/ml/ml_instance.cc index 1677d389..260b3c32 100644 --- a/src/ml/ml_instance.cc +++ b/src/ml/ml_instance.cc @@ -21,6 +21,7 @@ #include "common/logger.h" #include "common/picojson.h" #include "common/platform_result.h" +#include "common/tools.h" namespace extension { namespace ml { @@ -89,7 +90,7 @@ MlInstance::MlInstance() : pipeline_manager_{this} { REGISTER_METHOD(MLTensorsInfoDispose); // Single API begin - // MachineLearningSingle::openModel() + REGISTER_METHOD(MLSingleManagerOpenModel); // MachineLearningSingle::openModelAsync() // OpenModelSuccessCallback // SingleShot input @@ -534,7 +535,84 @@ void MlInstance::MLTensorsInfoDispose(const picojson::value& args, picojson::obj // Single API begin -// MachineLearningSingle::openModel() +// TODO move to the up section with field names +namespace { +const std::string kModelPath = "modelPath"; +const std::string kInTensorsInfo = "inTensorsInfo"; +const std::string kOutTensorsInfo = "outTensorsInfo"; +const std::string kFwType = "fwType"; +const std::string kHwType = "hwType"; +const std::string kIsDynamicMode = "isDynamicMode"; + +const int kNoId = -1; +} // namespace +void MlInstance::MLSingleManagerOpenModel(const picojson::value& args, picojson::object& out) { + ScopeLogger("args: %s", args.serialize().c_str()); + CHECK_ARGS(args, kModelPath, std::string, out); + CHECK_ARGS(args, kInTensorsInfo, double, out); + CHECK_ARGS(args, kOutTensorsInfo, double, out); + CHECK_ARGS(args, kFwType, std::string, out); + CHECK_ARGS(args, kHwType, std::string, out); + CHECK_ARGS(args, kIsDynamicMode, bool, out); + + const auto& model_path = common::tools::ConvertUriToPath(args.get(kModelPath).get()); + PlatformResult result = common::tools::CheckFileAvailability(model_path); + if (!result) { + LogAndReportError( + PlatformResult(ErrorCode::NOT_FOUND_ERR, "File does not exist or is not accessible"), &out, + ("File does not exist or is not accessible: %s", model_path.c_str())); + return; + } + + TensorsInfo* in_tensors_info = nullptr; + auto inTensorId = static_cast(args.get(kInTensorsInfo).get()); + if (kNoId != inTensorId) { + in_tensors_info = GetTensorsInfoManager().GetTensorsInfo(inTensorId); + if (nullptr == in_tensors_info) { + LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out, + ("Could not find TensorsInfo handle with given id: %d", inTensorId)); + return; + } + } + + TensorsInfo* out_tensors_info = nullptr; + auto outTensorId = static_cast(args.get(kOutTensorsInfo).get()); + if (kNoId != outTensorId) { + out_tensors_info = GetTensorsInfoManager().GetTensorsInfo(outTensorId); + if (nullptr == out_tensors_info) { + LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Internal TensorsInfo error"), &out, + ("Could not find TensorsInfo handle with given id: %d", outTensorId)); + return; + } + } + + ml_nnfw_type_e nnfw_e = ML_NNFW_TYPE_ANY; + result = types::NNFWTypeEnum.getValue(args.get(kFwType).get(), &nnfw_e); + if (!result) { + LogAndReportError(result, &out); + return; + } + + ml_nnfw_hw_e hw_e = ML_NNFW_HW_ANY; + result = types::HWTypeEnum.getValue(args.get(kHwType).get(), &hw_e); + if (!result) { + LogAndReportError(result, &out); + return; + } + + auto is_dynamic_mode = args.get(kIsDynamicMode).get(); + + int res_id = -1; + result = single_manager_.OpenModel(model_path, in_tensors_info, out_tensors_info, nnfw_e, hw_e, + is_dynamic_mode, &res_id); + if (!result) { + ReportError(result, &out); + return; + } + + out["id"] = picojson::value(static_cast(res_id)); + ReportSuccess(out); +} // MachineLearningSingle::openModelAsync() diff --git a/src/ml/ml_instance.h b/src/ml/ml_instance.h index d511e8da..5afbba36 100644 --- a/src/ml/ml_instance.h +++ b/src/ml/ml_instance.h @@ -20,6 +20,7 @@ #include "common/extension.h" #include "ml/ml_pipeline_manager.h" +#include "ml/ml_single_manager.h" #include "nnstreamer/nnstreamer-single.h" #include "nnstreamer/nnstreamer.h" @@ -54,7 +55,8 @@ class MlInstance : public common::ParsedInstance { // Common ML API end // Single API begin - // MachineLearningSingle::openModel() + SingleManager single_manager_; + void MLSingleManagerOpenModel(const picojson::value& args, picojson::object& out); // MachineLearningSingle::openModelAsync() // OpenModelSuccessCallback // SingleShot input diff --git a/src/ml/ml_single_manager.cc b/src/ml/ml_single_manager.cc new file mode 100644 index 00000000..00f813ff --- /dev/null +++ b/src/ml/ml_single_manager.cc @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 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 "ml_single_manager.h" +#include "common/tools.h" + +using common::PlatformResult; +using common::ErrorCode; + +namespace extension { +namespace ml { + +SingleManager::SingleManager() : nextId_{0} { + ScopeLogger(); +} + +SingleManager::~SingleManager() { + ScopeLogger(); +} + +// MachineLearningSingle::openModel() +PlatformResult SingleManager::OpenModel(const std::string& modelPath, TensorsInfo* inTensorsInfo, + TensorsInfo* outTensorsInfo, ml_nnfw_type_e nnfw_e, + ml_nnfw_hw_e hw_e, bool isDynamicMode, int* res_id) { + ScopeLogger(); + + ml_single_h handle = nullptr; + + ml_tensors_info_h in_info = inTensorsInfo ? inTensorsInfo->Handle() : nullptr; + ml_tensors_info_h out_info = outTensorsInfo ? outTensorsInfo->Handle() : nullptr; + + int ret = ml_single_open(&handle, modelPath.c_str(), in_info, out_info, nnfw_e, hw_e); + if (ML_ERROR_NONE != ret) { + LoggerE("ml_single_open failed: %d (%s)", ret, get_error_message(ret)); + return util::ToPlatformResult(ret, "Failed to open model"); + } + + int id = nextId_++; + singles_[id] = std::make_unique(id, handle); + *res_id = id; + return PlatformResult{}; +} + +// MachineLearningSingle::openModelAsync() +// OpenModelSuccessCallback +// SingleShot input +// SingleShot output +// SingleShot::invoke() +// SingleShot::getValue() +// SingleShot::setValue() +// SingleShot::setTimeout() +// SingleShot::close() + +} // namespace ml +} // namespace extension diff --git a/src/ml/ml_single_manager.h b/src/ml/ml_single_manager.h new file mode 100644 index 00000000..034fbff6 --- /dev/null +++ b/src/ml/ml_single_manager.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 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_SINGLE_MANAGER_H_ +#define ML_ML_SINGLE_MANAGER_H_ + +#include "common/platform_result.h" + +#include "ml_singleshot.h" +#include "ml_tensors_info_manager.h" +#include "nnstreamer/nnstreamer-single.h" + +using common::PlatformResult; + +namespace extension { +namespace ml { + +class SingleManager { + public: + SingleManager(); + ~SingleManager(); + + SingleManager(const SingleManager&) = delete; + SingleManager& operator=(const SingleManager&) = delete; + + // MachineLearningSingle::openModel() + PlatformResult OpenModel(const std::string& modelPath, TensorsInfo* inTensorsInfo, + TensorsInfo* outTensorsInfo, ml_nnfw_type_e nnfw_e, ml_nnfw_hw_e hw_e, + bool isDynamicMode, int* res_id); + // MachineLearningSingle::openModelAsync() + // OpenModelSuccessCallback + // SingleShot input + // SingleShot output + // SingleShot::invoke() + // SingleShot::getValue() + // SingleShot::setValue() + // SingleShot::setTimeout() + // SingleShot::close() + + private: + int nextId_; + std::map> singles_; +}; + +} // namespace ml +} // namespace extension + +#endif // ML_ML_SINGLE_MANAGER_H_ diff --git a/src/ml/ml_singleshot.cc b/src/ml/ml_singleshot.cc new file mode 100644 index 00000000..a9fb3a07 --- /dev/null +++ b/src/ml/ml_singleshot.cc @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 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 + +#include "common/logger.h" +#include "ml_singleshot.h" +#include "ml_utils.h" + +using common::PlatformResult; +using common::ErrorCode; + +namespace extension { +namespace ml { + +SingleShot::SingleShot(int id, ml_single_h handle) : id_{id}, handle_{handle} { + ScopeLogger("id: %d", id_); +} + +// 'this' owns a handle_, and invalidates 'o' +SingleShot::SingleShot(SingleShot&& o) : id_(o.id_), handle_(o.handle_) { + ScopeLogger("id: %d", id_); + o.handle_ = nullptr; +} + +SingleShot::~SingleShot() { + ScopeLogger("id: %d", id_); + int ret = ml_single_close(handle_); + if (ML_ERROR_NONE != ret) { + LoggerW("ml_single_close failed: %d (%s)", ret, get_error_message(ret)); + } +} + +// SingleShot input + +// SingleShot output + +// SingleShot::invoke() + +// SingleShot::getValue() + +// SingleShot::setValue() + +// SingleShot::setTimeout() + +// SingleShot::close() + +} // namespace extension +} // namespace ml diff --git a/src/ml/ml_singleshot.h b/src/ml/ml_singleshot.h new file mode 100644 index 00000000..0a02b0ee --- /dev/null +++ b/src/ml/ml_singleshot.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 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_SINGLESHOT_H_ +#define ML_ML_SINGLESHOT_H_ + +#include +#include + +#include + +#include "common/platform_result.h" + +using common::PlatformResult; + +namespace extension { +namespace ml { + +class SingleShot { + public: + SingleShot(int id, ml_single_h handle); + SingleShot() = delete; + // copy semantics + SingleShot(const SingleShot&) = delete; + SingleShot& operator=(const SingleShot&) = delete; + // move semantics + SingleShot(SingleShot&& o); + SingleShot& operator=(SingleShot&& o) = delete; + ~SingleShot(); + + // SingleShot input + + // SingleShot output + + // SingleShot::invoke() + + // SingleShot::getValue() + + // SingleShot::setValue() + + // SingleShot::setTimeout() + + // SingleShot::close() + + private: + const int id_; + ml_single_h handle_; +}; + +} // namespace ml +} // namespace extension + +#endif // ML_ML_SINGLESHOT_H_