+/*
+ * 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 <nnstreamer/nnstreamer.h>
+#include <utility>
+
+#include "common/tools.h"
+#include "ml_pipeline_custom_filter.h"
+#include "ml_utils.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace {
+
+const std::string kListenerId = "listenerId";
+
+} // namespace
+
+namespace extension {
+namespace ml {
+namespace pipeline {
+
+PlatformResult CustomFilter::CreateAndRegisterCustomFilter(
+ const std::string& name, const std::string& listener_name, TensorsInfo* input_tensors_info_ptr,
+ TensorsInfo* output_tensors_info_ptr, common::Instance* instance_ptr,
+ TensorsInfoManager* tensors_info_manager_ptr, TensorsDataManager* tensors_data_manager_ptr,
+ std::unique_ptr<CustomFilter>* out) {
+ ScopeLogger(
+ "name: [%s], listener_name: [%s], input_tensors_info::id: [%d], "
+ "output_tensors_info::id: [%d]",
+ name.c_str(), listener_name.c_str(), input_tensors_info_ptr->Id(),
+ output_tensors_info_ptr->Id());
+
+ auto* input_tensors_info_clone_ptr =
+ tensors_info_manager_ptr->CloneTensorsInfo(input_tensors_info_ptr);
+ if (!input_tensors_info_clone_ptr) {
+ return LogAndCreateResult(
+ ErrorCode::ABORT_ERR, "Could not register custom filter",
+ ("Could not clone TensorsInfo with id: [%d]", input_tensors_info_ptr->Id()));
+ }
+
+ auto* output_tensors_info_clone_ptr =
+ tensors_info_manager_ptr->CloneTensorsInfo(output_tensors_info_ptr);
+ if (!output_tensors_info_clone_ptr) {
+ return LogAndCreateResult(
+ ErrorCode::ABORT_ERR, "Could not register custom filter",
+ ("Could not clone TensorsInfo with id: [%d]", output_tensors_info_ptr->Id()));
+ }
+
+ auto custom_filter_ptr = std::unique_ptr<CustomFilter>(new (std::nothrow) CustomFilter{
+ name, listener_name, input_tensors_info_clone_ptr, output_tensors_info_clone_ptr,
+ instance_ptr, tensors_info_manager_ptr, tensors_data_manager_ptr,
+ std::this_thread::get_id()});
+ ;
+ if (!custom_filter_ptr) {
+ return LogAndCreateResult(ErrorCode::ABORT_ERR, "Could not register custom filter",
+ ("Could not allocate memory"));
+ }
+
+ ml_custom_easy_filter_h custom_filter_handle = nullptr;
+ auto ret = ml_pipeline_custom_easy_filter_register(
+ name.c_str(), input_tensors_info_ptr->Handle(), output_tensors_info_ptr->Handle(),
+ CustomFilterListener, static_cast<void*>(custom_filter_ptr.get()), &custom_filter_handle);
+ if (ML_ERROR_NONE != ret) {
+ LoggerE("ml_pipeline_custom_easy_filter_register() failed: [%d] (%s)", ret,
+ get_error_message(ret));
+ return util::ToPlatformResult(ret, "Could not register custom filter");
+ }
+ LoggerD("ml_pipeline_custom_easy_filter_register() succeeded");
+ custom_filter_ptr->custom_filter_ = custom_filter_handle;
+
+ *out = std::move(custom_filter_ptr);
+
+ return PlatformResult{};
+}
+
+CustomFilter::CustomFilter(const std::string& name, const std::string& listener_name,
+ TensorsInfo* input_tensors_info, TensorsInfo* output_tensors_info,
+ common::Instance* instance_ptr,
+ TensorsInfoManager* tensors_info_manager_ptr,
+ TensorsDataManager* tensors_data_manager_ptr,
+ const std::thread::id& main_thread_id)
+ : name_{name},
+ listener_name_{listener_name},
+ input_tensors_info_ptr_{input_tensors_info},
+ output_tensors_info_ptr_{output_tensors_info},
+ custom_filter_{nullptr},
+ instance_ptr_{instance_ptr},
+ tensors_info_manager_ptr_{tensors_info_manager_ptr},
+ tensors_data_manager_ptr_{tensors_data_manager_ptr},
+ main_thread_id_{main_thread_id} {
+ ScopeLogger(
+ "name_: [%s], listener_name_: [%s], input_tensors_info::id: [%d], "
+ "output_tensors_info::id: [%d]",
+ name_.c_str(), listener_name_.c_str(), input_tensors_info_ptr_->Id(),
+ output_tensors_info_ptr_->Id());
+}
+
+CustomFilter::~CustomFilter() {
+ ScopeLogger("name: [%s]_, listener_name_: [%s], custom_filter_: [%p]", name_.c_str(),
+ listener_name_.c_str(), custom_filter_);
+
+ Unregister();
+ tensors_info_manager_ptr_->DisposeTensorsInfo(input_tensors_info_ptr_);
+ tensors_info_manager_ptr_->DisposeTensorsInfo(output_tensors_info_ptr_);
+}
+
+PlatformResult CustomFilter::Unregister() {
+ ScopeLogger("name_: [%s], listener_name_: [%s], custom_filter_: [%p]", name_.c_str(),
+ listener_name_.c_str(), custom_filter_);
+
+ if (!custom_filter_) {
+ LoggerD("CustomFilter was already unregistered");
+ return PlatformResult{};
+ }
+
+ auto ret = ml_pipeline_custom_easy_filter_unregister(custom_filter_);
+ if (ML_ERROR_NONE != ret) {
+ LoggerE("ml_pipeline_custom_easy_filter_unregister() failed: [%d] (%s)", ret,
+ get_error_message(ret));
+ return util::ToPlatformResult(ret, "Could not unregister custom_filter");
+ }
+ LoggerD("ml_pipeline_custom_easy_filter_unregister() succeeded");
+
+ custom_filter_ = nullptr;
+
+ return PlatformResult{};
+}
+
+int CustomFilter::CustomFilterListener(const ml_tensors_data_h input_tensors_data,
+ ml_tensors_data_h output_tensors_data, void* user_data) {
+ ScopeLogger("input_tensors_data: [%p], tensors_info_out: [%p], user_data: [%p]",
+ input_tensors_data, output_tensors_data, user_data);
+ // TODO: in next commit
+ return -1;
+}
+
+} // namespace pipeline
+} // namespace ml
+} // namespace extension
\ No newline at end of file