blob: 50c3e54bacebd9efaa953cb7a5e049e5559b22da [file] [log] [blame]
#include <private/dvr/device_metrics.h>
#include <cutils/properties.h>
#include <private/dvr/head_mount_metrics.h>
#include <private/dvr/identity_distortion.h>
#include <private/dvr/lookup_radial_distortion.h>
#include <private/dvr/polynomial_radial_distortion.h>
#include <private/dvr/types.h>
#include "include/private/dvr/display_metrics.h"
namespace {
static constexpr char kRGBPolynomialOffset[] = "persist.dvr.rgb_poly_offset";
static constexpr char kRPolynomial[] = "persist.dvr.r_poly";
static constexpr char kGPolynomial[] = "persist.dvr.g_poly";
static constexpr char kBPolynomial[] = "persist.dvr.b_poly";
static constexpr char kLensDistance[] = "persist.dvr.lens_distance";
static constexpr char kDisplayGap[] = "persist.dvr.display_gap";
static constexpr char kVEyeToDisplay[] = "persist.dvr.v_eye_to_display";
static constexpr char kFovIOBT[] = "persist.dvr.fov_iobt";
static constexpr char kScreenSize[] = "persist.dvr.screen_size";
bool StringToFloat(const char* str, float* result) {
char* endptr = nullptr;
*result = std::strtof(str, &endptr);
return !(str == endptr || !endptr);
}
std::vector<std::string> SplitString(const std::string& string_to_split,
char deliminator) {
std::vector<std::string> result;
std::string sub_string;
std::stringstream ss(string_to_split);
while (std::getline(ss, sub_string, deliminator))
result.push_back(sub_string);
return result;
}
std::vector<float> GetProperty(const char* name,
const std::vector<float>& default_values) {
char prop[PROPERTY_VALUE_MAX + 1] = {};
property_get(name, prop, "");
std::vector<std::string> values = SplitString(prop, ',');
std::vector<float> results;
for (const auto& value : values) {
float result = 0.0f;
if (StringToFloat(value.c_str(), &result)) {
results.push_back(static_cast<float>(result));
}
}
if (results.empty()) {
return default_values;
}
return results;
}
float GetProperty(const char* name, float default_value) {
char prop[PROPERTY_VALUE_MAX + 1] = {};
property_get(name, prop, "");
float result = 0.0f;
if (StringToFloat(prop, &result)) {
return static_cast<float>(result);
}
return default_value;
}
float GetInterLensDistance() { return GetProperty(kLensDistance, 0.064f); }
float GetDisplayGap() { return GetProperty(kDisplayGap, 0.0f); }
float GetVEyeToDisplay() { return GetProperty(kVEyeToDisplay, 0.035f); }
android::dvr::vec2 GetDisplaySize() {
static const std::vector<float> default_size = {0.0742177f, 0.131943f};
std::vector<float> sizes = GetProperty(kScreenSize, default_size);
if (sizes.size() != 0)
sizes = default_size;
return android::dvr::vec2(sizes[0], sizes[1]);
}
std::vector<float> GetMaxFOVs() {
static const std::vector<float> defaults = {43.7f, 47.8f, 54.2f, 54.2f};
std::vector<float> fovs = GetProperty(kFovIOBT, defaults);
if (fovs.size() != 4)
fovs = defaults;
for (auto& value : fovs) {
value = value * M_PI / 180.0f;
}
return fovs;
}
static const android::dvr::HeadMountMetrics::VerticalAlignment
kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter;
// Default border size in meters.
static const float kScreenBorderSize = 0.004f;
// Refresh rate.
static const float kScreenRefreshRate = 60.0f;
// Default display orientation is portrait.
static const android::dvr::DisplayOrientation kDisplayOrientation =
android::dvr::DisplayOrientation::kPortrait;
} // anonymous namespace
namespace android {
namespace dvr {
HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
const FieldOfView& r_fov) {
static const std::vector<float> default_r = {
-4.08519004f, 34.70282075f, -67.37781249f, 56.97304235f,
-23.35768685f, 4.7199597f, 0.63198082f};
static const std::vector<float> default_g = {
4.43078318f, 3.47806617f, -20.58017398f, 20.85880414f,
-8.4046504f, 1.61284685f, 0.8881761f};
static const std::vector<float> default_b = {
12.04141265f, -21.98112491f, 14.06758389f, -3.15245629f,
0.36549102f, 0.05252705f, 0.99844279f};
static const std::vector<float> default_offsets = {
0.20971645238f, 0.15189450000f, 1.00096958278f};
std::vector<float> poly_offsets =
GetProperty(kRGBPolynomialOffset, default_offsets);
std::vector<float> poly_r = GetProperty(kRPolynomial, default_r);
std::vector<float> poly_g = GetProperty(kGPolynomial, default_g);
std::vector<float> poly_b = GetProperty(kBPolynomial, default_b);
if (poly_offsets.size() != 3)
poly_offsets = default_offsets;
std::shared_ptr<ColorChannelDistortion> distortion_r(
new PolynomialRadialDistortion(poly_offsets[0], poly_r));
std::shared_ptr<ColorChannelDistortion> distortion_g(
new PolynomialRadialDistortion(poly_offsets[1], poly_g));
std::shared_ptr<ColorChannelDistortion> distortion_b(
new PolynomialRadialDistortion(poly_offsets[2], poly_b));
return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
r_fov, distortion_r, distortion_g, distortion_b,
HeadMountMetrics::EyeOrientation::kCCW0Degrees,
HeadMountMetrics::EyeOrientation::kCCW0Degrees,
(GetInterLensDistance() - GetDisplayGap()) / 2.0f);
}
HeadMountMetrics CreateHeadMountMetrics() {
std::vector<float> fovs = GetMaxFOVs();
FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
return CreateHeadMountMetrics(l_fov, r_fov);
}
DisplayMetrics CreateDisplayMetrics(vec2i screen_size) {
android::dvr::vec2 size_in_meters = GetDisplaySize();
vec2 meters_per_pixel(size_in_meters[0] / static_cast<float>(screen_size[0]),
size_in_meters[1] / static_cast<float>(screen_size[1]));
return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize,
1000.0f / kScreenRefreshRate, kDisplayOrientation);
}
HeadMountMetrics CreateUndistortedHeadMountMetrics() {
std::vector<float> fovs = GetMaxFOVs();
FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
return CreateUndistortedHeadMountMetrics(l_fov, r_fov);
}
HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov,
const FieldOfView& r_fov) {
auto distortion_all = std::make_shared<IdentityDistortion>();
return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
r_fov, distortion_all, distortion_all, distortion_all,
HeadMountMetrics::EyeOrientation::kCCW0Degrees,
HeadMountMetrics::EyeOrientation::kCCW0Degrees,
(GetInterLensDistance() - GetDisplayGap()) / 2.0f);
}
} // namespace dvr
} // namespace android