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 | |
| 13 | static constexpr char kRGBPolynomialOffset[] = "persist.dvr.rgb_poly_offset"; |
| 14 | static constexpr char kRPolynomial[] = "persist.dvr.r_poly"; |
| 15 | static constexpr char kGPolynomial[] = "persist.dvr.g_poly"; |
| 16 | static constexpr char kBPolynomial[] = "persist.dvr.b_poly"; |
| 17 | static constexpr char kLensDistance[] = "persist.dvr.lens_distance"; |
| 18 | static constexpr char kDisplayGap[] = "persist.dvr.display_gap"; |
| 19 | static constexpr char kVEyeToDisplay[] = "persist.dvr.v_eye_to_display"; |
| 20 | static constexpr char kFovIOBT[] = "persist.dvr.fov_iobt"; |
| 21 | static constexpr char kScreenSize[] = "persist.dvr.screen_size"; |
| 22 | |
| 23 | bool StringToFloat(const char* str, float* result) { |
| 24 | char* endptr = nullptr; |
| 25 | *result = std::strtof(str, &endptr); |
| 26 | return !(str == endptr || !endptr); |
| 27 | } |
| 28 | |
| 29 | std::vector<std::string> SplitString(const std::string& string_to_split, |
| 30 | char deliminator) { |
| 31 | std::vector<std::string> result; |
| 32 | std::string sub_string; |
| 33 | std::stringstream ss(string_to_split); |
| 34 | while (std::getline(ss, sub_string, deliminator)) |
| 35 | result.push_back(sub_string); |
| 36 | return result; |
| 37 | } |
| 38 | |
| 39 | std::vector<float> GetProperty(const char* name, |
| 40 | const std::vector<float>& default_values) { |
| 41 | char prop[PROPERTY_VALUE_MAX + 1] = {}; |
| 42 | property_get(name, prop, ""); |
| 43 | std::vector<std::string> values = SplitString(prop, ','); |
| 44 | std::vector<float> results; |
| 45 | for (const auto& value : values) { |
| 46 | float result = 0.0f; |
| 47 | if (StringToFloat(value.c_str(), &result)) { |
| 48 | results.push_back(static_cast<float>(result)); |
| 49 | } |
| 50 | } |
| 51 | if (results.empty()) { |
| 52 | return default_values; |
| 53 | } |
| 54 | return results; |
| 55 | } |
| 56 | |
| 57 | float GetProperty(const char* name, float default_value) { |
| 58 | char prop[PROPERTY_VALUE_MAX + 1] = {}; |
| 59 | property_get(name, prop, ""); |
| 60 | float result = 0.0f; |
| 61 | if (StringToFloat(prop, &result)) { |
| 62 | return static_cast<float>(result); |
| 63 | } |
| 64 | return default_value; |
| 65 | } |
| 66 | |
| 67 | float GetInterLensDistance() { return GetProperty(kLensDistance, 0.064f); } |
| 68 | |
| 69 | float GetDisplayGap() { return GetProperty(kDisplayGap, 0.0f); } |
| 70 | |
| 71 | float GetVEyeToDisplay() { return GetProperty(kVEyeToDisplay, 0.035f); } |
| 72 | |
| 73 | android::dvr::vec2 GetDisplaySize() { |
| 74 | static const std::vector<float> default_size = {0.0742177f, 0.131943f}; |
| 75 | std::vector<float> sizes = GetProperty(kScreenSize, default_size); |
| 76 | if (sizes.size() != 0) |
| 77 | sizes = default_size; |
| 78 | return android::dvr::vec2(sizes[0], sizes[1]); |
| 79 | } |
| 80 | |
| 81 | std::vector<float> GetMaxFOVs() { |
| 82 | static const std::vector<float> defaults = {43.7f, 47.8f, 54.2f, 54.2f}; |
| 83 | std::vector<float> fovs = GetProperty(kFovIOBT, defaults); |
| 84 | if (fovs.size() != 4) |
| 85 | fovs = defaults; |
| 86 | for (auto& value : fovs) { |
| 87 | value = value * M_PI / 180.0f; |
| 88 | } |
| 89 | return fovs; |
| 90 | } |
| 91 | |
| 92 | static const android::dvr::HeadMountMetrics::VerticalAlignment |
| 93 | kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter; |
| 94 | |
| 95 | // Default border size in meters. |
| 96 | static const float kScreenBorderSize = 0.004f; |
| 97 | |
| 98 | // Refresh rate. |
| 99 | static const float kScreenRefreshRate = 60.0f; |
| 100 | |
| 101 | // Default display orientation is portrait. |
| 102 | static const android::dvr::DisplayOrientation kDisplayOrientation = |
| 103 | android::dvr::DisplayOrientation::kPortrait; |
| 104 | |
| 105 | } // anonymous namespace |
| 106 | |
| 107 | namespace android { |
| 108 | namespace dvr { |
| 109 | |
| 110 | HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov, |
| 111 | const FieldOfView& r_fov) { |
| 112 | static const std::vector<float> default_r = { |
| 113 | -4.08519004f, 34.70282075f, -67.37781249f, 56.97304235f, |
| 114 | -23.35768685f, 4.7199597f, 0.63198082f}; |
| 115 | static const std::vector<float> default_g = { |
| 116 | 4.43078318f, 3.47806617f, -20.58017398f, 20.85880414f, |
| 117 | -8.4046504f, 1.61284685f, 0.8881761f}; |
| 118 | static const std::vector<float> default_b = { |
| 119 | 12.04141265f, -21.98112491f, 14.06758389f, -3.15245629f, |
| 120 | 0.36549102f, 0.05252705f, 0.99844279f}; |
| 121 | static const std::vector<float> default_offsets = { |
| 122 | 0.20971645238f, 0.15189450000f, 1.00096958278f}; |
| 123 | |
| 124 | std::vector<float> poly_offsets = |
| 125 | GetProperty(kRGBPolynomialOffset, default_offsets); |
| 126 | std::vector<float> poly_r = GetProperty(kRPolynomial, default_r); |
| 127 | std::vector<float> poly_g = GetProperty(kGPolynomial, default_g); |
| 128 | std::vector<float> poly_b = GetProperty(kBPolynomial, default_b); |
| 129 | if (poly_offsets.size() != 3) |
| 130 | poly_offsets = default_offsets; |
| 131 | |
| 132 | std::shared_ptr<ColorChannelDistortion> distortion_r( |
| 133 | new PolynomialRadialDistortion(poly_offsets[0], poly_r)); |
| 134 | std::shared_ptr<ColorChannelDistortion> distortion_g( |
| 135 | new PolynomialRadialDistortion(poly_offsets[1], poly_g)); |
| 136 | std::shared_ptr<ColorChannelDistortion> distortion_b( |
| 137 | new PolynomialRadialDistortion(poly_offsets[2], poly_b)); |
| 138 | |
| 139 | return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(), |
| 140 | GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov, |
| 141 | r_fov, distortion_r, distortion_g, distortion_b, |
| 142 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 143 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 144 | (GetInterLensDistance() - GetDisplayGap()) / 2.0f); |
| 145 | } |
| 146 | |
| 147 | HeadMountMetrics CreateHeadMountMetrics() { |
| 148 | std::vector<float> fovs = GetMaxFOVs(); |
| 149 | FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]); |
| 150 | FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]); |
| 151 | return CreateHeadMountMetrics(l_fov, r_fov); |
| 152 | } |
| 153 | |
| 154 | DisplayMetrics CreateDisplayMetrics(vec2i screen_size) { |
| 155 | android::dvr::vec2 size_in_meters = GetDisplaySize(); |
| 156 | vec2 meters_per_pixel(size_in_meters[0] / static_cast<float>(screen_size[0]), |
| 157 | size_in_meters[1] / static_cast<float>(screen_size[1])); |
| 158 | return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize, |
| 159 | 1000.0f / kScreenRefreshRate, kDisplayOrientation); |
| 160 | } |
| 161 | |
| 162 | HeadMountMetrics CreateUndistortedHeadMountMetrics() { |
| 163 | std::vector<float> fovs = GetMaxFOVs(); |
| 164 | FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]); |
| 165 | FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]); |
| 166 | return CreateUndistortedHeadMountMetrics(l_fov, r_fov); |
| 167 | } |
| 168 | |
| 169 | HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov, |
| 170 | const FieldOfView& r_fov) { |
| 171 | auto distortion_all = std::make_shared<IdentityDistortion>(); |
| 172 | |
| 173 | return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(), |
| 174 | GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov, |
| 175 | r_fov, distortion_all, distortion_all, distortion_all, |
| 176 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 177 | HeadMountMetrics::EyeOrientation::kCCW0Degrees, |
| 178 | (GetInterLensDistance() - GetDisplayGap()) / 2.0f); |
| 179 | } |
| 180 | |
| 181 | } // namespace dvr |
| 182 | } // namespace android |