Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 1 | #include <private/dvr/device_metrics.h> |
| 2 | |
| 3 | #include <cutils/properties.h> |
| 4 | #include <private/dvr/head_mount_metrics.h> |
| 5 | #include <private/dvr/identity_distortion.h> |
| 6 | #include <private/dvr/lookup_radial_distortion.h> |
| 7 | #include <private/dvr/polynomial_radial_distortion.h> |
| 8 | #include <private/dvr/types.h> |
| 9 | #include "include/private/dvr/display_metrics.h" |
| 10 | |
| 11 | namespace { |
| 12 | |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 13 | static constexpr char kRPolynomial[] = "persist.dvr.r_poly"; |
| 14 | static constexpr char kGPolynomial[] = "persist.dvr.g_poly"; |
| 15 | static constexpr char kBPolynomial[] = "persist.dvr.b_poly"; |
| 16 | static constexpr char kLensDistance[] = "persist.dvr.lens_distance"; |
| 17 | static constexpr char kDisplayGap[] = "persist.dvr.display_gap"; |
| 18 | static constexpr char kVEyeToDisplay[] = "persist.dvr.v_eye_to_display"; |
| 19 | static constexpr char kFovIOBT[] = "persist.dvr.fov_iobt"; |
| 20 | static constexpr char kScreenSize[] = "persist.dvr.screen_size"; |
| 21 | |
| 22 | bool StringToFloat(const char* str, float* result) { |
| 23 | char* endptr = nullptr; |
| 24 | *result = std::strtof(str, &endptr); |
| 25 | return !(str == endptr || !endptr); |
| 26 | } |
| 27 | |
| 28 | std::vector<std::string> SplitString(const std::string& string_to_split, |
| 29 | char deliminator) { |
| 30 | std::vector<std::string> result; |
| 31 | std::string sub_string; |
| 32 | std::stringstream ss(string_to_split); |
| 33 | while (std::getline(ss, sub_string, deliminator)) |
| 34 | result.push_back(sub_string); |
| 35 | return result; |
| 36 | } |
| 37 | |
| 38 | std::vector<float> GetProperty(const char* name, |
| 39 | const std::vector<float>& default_values) { |
| 40 | char prop[PROPERTY_VALUE_MAX + 1] = {}; |
| 41 | property_get(name, prop, ""); |
| 42 | std::vector<std::string> values = SplitString(prop, ','); |
| 43 | std::vector<float> results; |
| 44 | for (const auto& value : values) { |
| 45 | float result = 0.0f; |
| 46 | if (StringToFloat(value.c_str(), &result)) { |
| 47 | results.push_back(static_cast<float>(result)); |
| 48 | } |
| 49 | } |
| 50 | if (results.empty()) { |
| 51 | return default_values; |
| 52 | } |
| 53 | return results; |
| 54 | } |
| 55 | |
| 56 | float GetProperty(const char* name, float default_value) { |
| 57 | char prop[PROPERTY_VALUE_MAX + 1] = {}; |
| 58 | property_get(name, prop, ""); |
| 59 | float result = 0.0f; |
| 60 | if (StringToFloat(prop, &result)) { |
| 61 | return static_cast<float>(result); |
| 62 | } |
| 63 | return default_value; |
| 64 | } |
| 65 | |
| 66 | float GetInterLensDistance() { return GetProperty(kLensDistance, 0.064f); } |
| 67 | |
| 68 | float GetDisplayGap() { return GetProperty(kDisplayGap, 0.0f); } |
| 69 | |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 70 | float GetTrayToLensDistance() { return 0.035f; } |
| 71 | |
| 72 | float GetVEyeToDisplay() { return GetProperty(kVEyeToDisplay, 0.042f); } |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 73 | |
| 74 | android::dvr::vec2 GetDisplaySize() { |
| 75 | static const std::vector<float> default_size = {0.0742177f, 0.131943f}; |
| 76 | std::vector<float> sizes = GetProperty(kScreenSize, default_size); |
| 77 | if (sizes.size() != 0) |
| 78 | sizes = default_size; |
| 79 | return android::dvr::vec2(sizes[0], sizes[1]); |
| 80 | } |
| 81 | |
| 82 | std::vector<float> GetMaxFOVs() { |
| 83 | static const std::vector<float> defaults = {43.7f, 47.8f, 54.2f, 54.2f}; |
| 84 | std::vector<float> fovs = GetProperty(kFovIOBT, defaults); |
| 85 | if (fovs.size() != 4) |
| 86 | fovs = defaults; |
| 87 | for (auto& value : fovs) { |
| 88 | value = value * M_PI / 180.0f; |
| 89 | } |
| 90 | return fovs; |
| 91 | } |
| 92 | |
| 93 | static const android::dvr::HeadMountMetrics::VerticalAlignment |
| 94 | kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter; |
| 95 | |
| 96 | // Default border size in meters. |
| 97 | static const float kScreenBorderSize = 0.004f; |
| 98 | |
| 99 | // Refresh rate. |
| 100 | static const float kScreenRefreshRate = 60.0f; |
| 101 | |
| 102 | // Default display orientation is portrait. |
| 103 | static const android::dvr::DisplayOrientation kDisplayOrientation = |
| 104 | android::dvr::DisplayOrientation::kPortrait; |
| 105 | |
| 106 | } // anonymous namespace |
| 107 | |
| 108 | namespace android { |
| 109 | namespace dvr { |
| 110 | |
| 111 | HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov, |
| 112 | const FieldOfView& r_fov) { |
| 113 | static const std::vector<float> default_r = { |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 114 | 0.00103f, 2.63917f, -7.14427f, 8.98036f, -4.10586f, 0.83705f, 0.00130f}; |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 115 | static const std::vector<float> default_g = { |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 116 | 0.08944f, 2.26005f, -6.30924f, 7.94561f, -3.22788f, 0.45577f, 0.07300f}; |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 117 | static const std::vector<float> default_b = { |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 118 | 0.16364f, 1.94083f, -5.55033f, 6.89578f, -2.19053f, -0.04050f, 0.17380f}; |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 119 | std::vector<float> poly_r = GetProperty(kRPolynomial, default_r); |
| 120 | std::vector<float> poly_g = GetProperty(kGPolynomial, default_g); |
| 121 | std::vector<float> poly_b = GetProperty(kBPolynomial, default_b); |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 122 | |
| 123 | std::shared_ptr<ColorChannelDistortion> distortion_r( |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 124 | new PolynomialRadialDistortion(poly_r)); |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 125 | std::shared_ptr<ColorChannelDistortion> distortion_g( |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 126 | new PolynomialRadialDistortion(poly_g)); |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 127 | std::shared_ptr<ColorChannelDistortion> distortion_b( |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 128 | new PolynomialRadialDistortion(poly_b)); |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 129 | |
Hendrik Wagenaar | f8b1ef4 | 2017-04-18 15:12:30 -0700 | [diff] [blame^] | 130 | return HeadMountMetrics(GetInterLensDistance(), GetTrayToLensDistance(), |
Hendrik Wagenaar | 302b74f | 2017-04-04 14:38:36 -0700 | [diff] [blame] | 131 | GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov, |
| 132 | r_fov, distortion_r, distortion_g, distortion_b, |
| 133 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 134 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 135 | (GetInterLensDistance() - GetDisplayGap()) / 2.0f); |
| 136 | } |
| 137 | |
| 138 | HeadMountMetrics CreateHeadMountMetrics() { |
| 139 | std::vector<float> fovs = GetMaxFOVs(); |
| 140 | FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]); |
| 141 | FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]); |
| 142 | return CreateHeadMountMetrics(l_fov, r_fov); |
| 143 | } |
| 144 | |
| 145 | DisplayMetrics CreateDisplayMetrics(vec2i screen_size) { |
| 146 | android::dvr::vec2 size_in_meters = GetDisplaySize(); |
| 147 | vec2 meters_per_pixel(size_in_meters[0] / static_cast<float>(screen_size[0]), |
| 148 | size_in_meters[1] / static_cast<float>(screen_size[1])); |
| 149 | return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize, |
| 150 | 1000.0f / kScreenRefreshRate, kDisplayOrientation); |
| 151 | } |
| 152 | |
| 153 | HeadMountMetrics CreateUndistortedHeadMountMetrics() { |
| 154 | std::vector<float> fovs = GetMaxFOVs(); |
| 155 | FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]); |
| 156 | FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]); |
| 157 | return CreateUndistortedHeadMountMetrics(l_fov, r_fov); |
| 158 | } |
| 159 | |
| 160 | HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov, |
| 161 | const FieldOfView& r_fov) { |
| 162 | auto distortion_all = std::make_shared<IdentityDistortion>(); |
| 163 | |
| 164 | return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(), |
| 165 | GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov, |
| 166 | r_fov, distortion_all, distortion_all, distortion_all, |
| 167 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 168 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 169 | (GetInterLensDistance() - GetDisplayGap()) / 2.0f); |
| 170 | } |
| 171 | |
| 172 | } // namespace dvr |
| 173 | } // namespace android |