diff --git a/mediapipe/util/BUILD b/mediapipe/util/BUILD index cd82a850a..e12e04050 100644 --- a/mediapipe/util/BUILD +++ b/mediapipe/util/BUILD @@ -188,6 +188,8 @@ cc_library( srcs = [ "resource_util.cc", "resource_util_internal.h", + "resource_path_manager.cc", + "resource_path_manager.h", ] + select({ "//conditions:default": ["resource_util_default.cc"], "//mediapipe:android": ["resource_util_android.cc"], diff --git a/mediapipe/util/resource_path_manager.cc b/mediapipe/util/resource_path_manager.cc new file mode 100644 index 000000000..f3806be8d --- /dev/null +++ b/mediapipe/util/resource_path_manager.cc @@ -0,0 +1,47 @@ +// Copyright 2019 The MediaPipe Authors. +// +// 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 "mediapipe/util/resource_path_manager.h" + +#include + +#include "absl/strings/str_split.h" +#include "mediapipe/framework/deps/file_path.h" +#include "mediapipe/framework/port/file_helpers.h" +#include "mediapipe/framework/port/ret_check.h" + +namespace mediapipe { + +std::vector resource_search_paths_; + +void ResourcePathManager::AddSearchPath(const std::string& path) +{ + resource_search_paths_.push_back(path); +} + +absl::StatusOr ResourcePathManager::ResolveFilePath(const std::string& path) +{ + if (absl::StartsWith(path, "/")) { + return path; + } + for (auto & resource_path: resource_search_paths_) { + auto file_path = file::JoinPath(resource_path, path); + if (file::Exists(file_path).ok()) { + return file_path; + } + } + return absl::NotFoundError("No file " + path + " found in declared search paths"); +} + +} // namespace mediapipe diff --git a/mediapipe/util/resource_path_manager.h b/mediapipe/util/resource_path_manager.h new file mode 100644 index 000000000..ad91c0760 --- /dev/null +++ b/mediapipe/util/resource_path_manager.h @@ -0,0 +1,36 @@ +// Copyright 2019 The MediaPipe Authors. +// +// 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 MEDIAPIPE_UTIL_RESOURCE_PATH_MANAGER_H_ +#define MEDIAPIPE_UTIL_RESOURCE_PATH_MANAGER_H_ + +#include + +#include "mediapipe/framework/port/statusor.h" + +namespace mediapipe { + +// The ResourcePathManager provides additionnal search paths handling for resources (tflite...) locations. +class ResourcePathManager { + public: + // Adds a path to search resources for. + static void AddSearchPath(const std::string& path); + // Tries to resolve a filepath from path and previously added search path. + // Either return the filepath when it exists, or absl::NotFoundError when the path doesn't exists. + static absl::StatusOr ResolveFilePath(const std::string& path); +}; + +} // namespace mediapipe + +#endif // MEDIAPIPE_UTIL_RESOURCE_UTIL_H_ diff --git a/mediapipe/util/resource_util_android.cc b/mediapipe/util/resource_util_android.cc index 1e970f212..65d413456 100644 --- a/mediapipe/util/resource_util_android.cc +++ b/mediapipe/util/resource_util_android.cc @@ -21,6 +21,7 @@ #include "mediapipe/framework/port/statusor.h" #include "mediapipe/util/android/asset_manager_util.h" #include "mediapipe/util/android/file/base/helpers.h" +#include "mediapipe/util/resource_path_manager.h" namespace mediapipe { @@ -79,6 +80,15 @@ absl::StatusOr PathToResourceAsFile(const std::string& path) { } } + // try to load file in potentially declared resource paths + { + auto status_or_path = ResourcePathManager::ResolveFilePath(path); + if (status_or_path.ok()) { + LOG(INFO) << "Successfully loaded: " << path; + return status_or_path; + } + } + // If that fails, assume it was a relative path, and try just the base name. { const size_t last_slash_idx = path.find_last_of("\\/"); diff --git a/mediapipe/util/resource_util_apple.cc b/mediapipe/util/resource_util_apple.cc index f64718348..8d21c0b0d 100644 --- a/mediapipe/util/resource_util_apple.cc +++ b/mediapipe/util/resource_util_apple.cc @@ -22,6 +22,7 @@ #include "mediapipe/framework/port/ret_check.h" #include "mediapipe/framework/port/statusor.h" #include "mediapipe/util/resource_util.h" +#include "mediapipe/util/resource_path_manager.h" namespace mediapipe { @@ -59,6 +60,15 @@ absl::StatusOr PathToResourceAsFile(const std::string& path) { return path; } + // try to load file in potentially declared resource paths + { + auto status_or_path = ResourcePathManager::ResolveFilePath(path); + if (status_or_path.ok()) { + LOG(INFO) << "Successfully loaded: " << path; + return status_or_path; + } + } + // Try to load a relative path or a base filename as is. { auto status_or_path = PathToResourceAsFileInternal(path); diff --git a/mediapipe/util/resource_util_default.cc b/mediapipe/util/resource_util_default.cc index 3ebbd1f34..328f25b67 100644 --- a/mediapipe/util/resource_util_default.cc +++ b/mediapipe/util/resource_util_default.cc @@ -18,6 +18,7 @@ #include "mediapipe/framework/deps/file_path.h" #include "mediapipe/framework/port/file_helpers.h" #include "mediapipe/framework/port/statusor.h" +#include "mediapipe/util/resource_path_manager.h" ABSL_FLAG( std::string, resource_root_dir, "", @@ -43,6 +44,15 @@ absl::StatusOr PathToResourceAsFile(const std::string& path) { return path; } + // try to load file in potentially declared resource paths + { + auto status_or_path = ResourcePathManager::ResolveFilePath(path); + if (status_or_path.ok()) { + LOG(INFO) << "Successfully loaded: " << path; + return status_or_path; + } + } + // Try to load the file from bazel-bin. If it does not exist, fall back to the // resource folder. auto bazel_path = JoinPath("bazel-bin", path);