blob: 72d6960ea93d017a472d0f63b3568c81122bbde8 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_CAMERA_DRIVERS_CONTROLLER_UTIL_H_
#define SRC_CAMERA_DRIVERS_CONTROLLER_UTIL_H_
#include <lib/fit/function.h>
#include <lib/fpromise/promise.h>
#include <lib/stdcompat/source_location.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/vmo.h>
#include <zircon/assert.h>
#include <zircon/status.h>
#include <algorithm>
#include <string>
#include "src/camera/drivers/controller/configs/internal_config.h"
#include "src/camera/lib/numerics/rational.h"
namespace camera {
using LoadFirmwareCallback =
fit::function<fpromise::result<std::pair<zx::vmo, size_t>, zx_status_t>(const std::string&)>;
inline fit::function<void(zx_status_t)> MakeErrorHandler(
bool panic = true, cpp20::source_location location = cpp20::source_location::current()) {
std::string origin;
if (location.file_name()) {
origin += location.file_name();
} else {
origin += "<unknown>";
}
origin += ":" + std::to_string(location.line());
if (location.function_name()) {
origin += " (" + std::string(location.file_name()) + ")";
}
return [origin, panic](zx_status_t status) {
auto message = "Unexpected error from " + origin;
FX_PLOGS(ERROR, status) << message;
if (panic) {
ZX_PANIC("%s: %s", message.c_str(), zx_status_get_string(status));
}
};
}
inline constexpr const char* NodeTypeName(const InternalConfigNode& node) {
switch (node.type) {
case NodeType::kInputStream:
return "input";
case NodeType::kGdc:
return "gdc";
case NodeType::kGe2d:
return "ge2d";
case NodeType::kOutputStream:
return "output";
case NodeType::kPassthrough:
return "passthrough";
default:
return "<invalid>";
}
}
// This function helps chain together async methods to provide continuation semantics. While inline
// lambdas can easily transform `foo(callback)` into `bar([&]{foo(callback);})`, this function can
// transform it into a form equivalent to `foo([&]{bar(callback);})`
inline fit::function<void(fit::closure)> MakeContinuation(fit::function<void(fit::closure)> func,
fit::function<void(fit::closure)> then) {
return [func = std::move(func), then = std::move(then)](fit::closure callback) mutable {
func([then = std::move(then), callback = std::move(callback)]() mutable {
then(std::move(callback));
});
};
}
// Converts a camera2.FrameRate (Hz) to a frame time interval (seconds).
inline numerics::Rational FramerateToInterval(const fuchsia::camera2::FrameRate& fps) {
ZX_ASSERT(fps.frames_per_sec_numerator > 0);
ZX_ASSERT(fps.frames_per_sec_denominator > 0);
// Note: the swap of numerator and denominator fields is intentional.
numerics::Rational interval{.n = fps.frames_per_sec_denominator,
.d = fps.frames_per_sec_numerator};
interval.Reduce();
return interval;
}
// Syntactic sugar for vector move-append.
template <typename T>
static std::vector<T>& operator+=(std::vector<T>& a, std::vector<T>&& b) {
assert(&a != &b);
a.reserve(a.size() + b.size());
std::move(b.begin(), b.end(), std::back_inserter(a));
return a;
}
// This method extends fit::bind_member with an implicit derived-class cast.
template <typename R, typename T, typename U = T, typename... Args>
auto BindPolyMethod(T* instance, R (U::*fn)(Args...)) {
static_assert(std::is_base_of_v<T, U>, "BindPolyMethod requires compatible types.");
return fit::bind_member(static_cast<U*>(instance), fn);
}
// Formats a vector into a string using the given separators.
template <typename T>
std::string Format(const std::vector<T>& v,
const std::array<char, 3> separators = {'[', ']', ':'}) {
std::string formatted;
formatted += separators[0];
for (const auto& e : v) {
formatted += std::to_string(e) + separators[2];
}
formatted.pop_back();
formatted += separators[1];
return formatted;
}
// Invokes the provided function for each line (spans between newline characters) of the provided
// string. This is used for breaking up long syslog messages to stay under the message size limit.
inline void ForEachLine(const std::string& s, fit::function<void(const std::string&)> fn) {
auto begin = s.begin();
while (begin != s.end()) {
auto it = std::find(begin, s.end(), '\n');
std::string str(begin, it);
fn(str);
begin = it;
}
}
} // namespace camera
#endif // SRC_CAMERA_DRIVERS_CONTROLLER_UTIL_H_