| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "camera_characteristics.h" |
| 6 |
| 7 #include <base/files/file_util.h> |
| 8 #include <base/logging.h> |
| 9 |
| 10 namespace media { |
| 11 |
| 12 // /etc/camera/camera_characteristics.conf contains camera information which |
| 13 // driver cannot provide. |
| 14 static const char kCameraCharacteristicsConfigFile[] = |
| 15 "/etc/camera/camera_characteristics.conf"; |
| 16 static const char kLensFacing[] = "lens_facing"; |
| 17 static const char kSensorOrientation[] = "sensor_orientation"; |
| 18 static const char kUsbVidPid[] = "usb_vid_pid"; |
| 19 static const char kFramesToSkipAfterStreamon[] = |
| 20 "frames_to_skip_after_streamon"; |
| 21 static const char kHorizontalViewAngle_16_9[] = "horizontal_view_angle_16_9"; |
| 22 static const char kHorizontalViewAngle_4_3[] = "horizontal_view_angle_4_3"; |
| 23 static const char kLensInfoAvailableFocalLengths[] = |
| 24 "lens_info_available_focal_lengths"; |
| 25 static const char kLensInfoMinimumFocusDistance[] = |
| 26 "lens_info_minimum_focus_distance"; |
| 27 static const char kLensInfoOptimalFocusDistance[] = |
| 28 "lens_info_optimal_focus_distance"; |
| 29 static const char kVerticalViewAngle_16_9[] = "vertical_view_angle_16_9"; |
| 30 static const char kVerticalViewAngle_4_3[] = "vertical_view_angle_4_3"; |
| 31 |
| 32 /* HAL v3 parameters */ |
| 33 static const char kLensInfoAvailableApertures[] = |
| 34 "lens_info_available_apertures"; |
| 35 static const char kSensorInfoPhysicalSize[] = "sensor_info_physical_size"; |
| 36 static const char kSensorInfoPixelArraySize[] = "sensor_info_pixel_array_size"; |
| 37 |
| 38 static const struct DeviceInfo kDefaultCharacteristics = { |
| 39 "", // device_path |
| 40 "", // usb_vid |
| 41 "", // usb_pid |
| 42 0, // lens_facing |
| 43 0, // sensor_orientation |
| 44 0, // frames_to_skip_after_streamon |
| 45 66.5, // horizontal_view_angle_16_9 |
| 46 0.0, // horizontal_view_angle_4_3 |
| 47 {1.6}, // lens_info_available_focal_lengths |
| 48 0.3, // lens_info_minimum_focus_distance |
| 49 0.5, // lens_info_optimal_focus_distance |
| 50 42.5, // vertical_view_angle_16_9 |
| 51 0.0 // vertical_view_angle_4_3 |
| 52 }; |
| 53 |
| 54 CameraCharacteristics::CameraCharacteristics() {} |
| 55 |
| 56 CameraCharacteristics::~CameraCharacteristics() {} |
| 57 |
| 58 const DeviceInfos CameraCharacteristics::GetCharacteristicsFromFile( |
| 59 const std::vector<std::string>& devices) { |
| 60 const base::FilePath path(kCameraCharacteristicsConfigFile); |
| 61 FILE* file = base::OpenFile(path, "r"); |
| 62 if (!file) { |
| 63 LOG(ERROR) << __func__ << ": Can't open file " |
| 64 << kCameraCharacteristicsConfigFile |
| 65 << ". Use default characteristics instead"; |
| 66 for (const auto& device : devices) { |
| 67 device_infos_.push_back(kDefaultCharacteristics); |
| 68 size_t pos = device.find(":"); |
| 69 if (pos != std::string::npos) { |
| 70 device_infos_.back().usb_vid = device.substr(0, pos - 1); |
| 71 device_infos_.back().usb_pid = device.substr(pos + 1); |
| 72 } else { |
| 73 LOG(ERROR) << __func__ << ": Invalid device: " << device; |
| 74 } |
| 75 } |
| 76 return device_infos_; |
| 77 } |
| 78 |
| 79 char buffer[256], key[256], value[256]; |
| 80 uint32_t camera_id; |
| 81 uint32_t module_id = -1; |
| 82 std::string vid, pid; |
| 83 while (fgets(buffer, sizeof(buffer), file)) { |
| 84 // Skip comments and empty lines. |
| 85 if (buffer[0] == '#' || buffer[0] == '\n') { |
| 86 continue; |
| 87 } |
| 88 |
| 89 if (sscanf(buffer, "%[^=]=%s", key, value) != 2) { |
| 90 LOG(ERROR) << __func__ << ": Illegal format: " << buffer; |
| 91 continue; |
| 92 } |
| 93 std::vector<char*> sub_keys; |
| 94 char* sub_key = strtok(key, "."); |
| 95 while (sub_key) { |
| 96 sub_keys.push_back(sub_key); |
| 97 sub_key = strtok(NULL, "."); |
| 98 } |
| 99 |
| 100 if (sscanf(sub_keys[0], "camera%u", &camera_id) != 1) { |
| 101 LOG(ERROR) << __func__ << ": Illegal format: " << sub_keys[0]; |
| 102 continue; |
| 103 } |
| 104 if (camera_id > device_infos_.size()) { |
| 105 // Camera id should be ascending by one. |
| 106 LOG(ERROR) << __func__ << ": Invalid camera id: " << camera_id; |
| 107 continue; |
| 108 } else if (camera_id == device_infos_.size()) { |
| 109 device_infos_.push_back(kDefaultCharacteristics); |
| 110 } |
| 111 |
| 112 uint32_t tmp_module_id; |
| 113 if (sscanf(sub_keys[1], "module%u", &tmp_module_id) != 1) { |
| 114 AddPerCameraCharacteristic(camera_id, sub_keys[1], value); |
| 115 } else { |
| 116 if (tmp_module_id != module_id) { |
| 117 vid.clear(); |
| 118 pid.clear(); |
| 119 module_id = tmp_module_id; |
| 120 } |
| 121 if (strcmp(sub_keys[2], kUsbVidPid) == 0) { |
| 122 char tmp_vid[256], tmp_pid[256]; |
| 123 if (sscanf(value, "%[0-9a-z]:%[0-9a-z]", tmp_vid, tmp_pid) != 2) { |
| 124 LOG(ERROR) << __func__ << ": Invalid format: " << sub_keys[2]; |
| 125 continue; |
| 126 } |
| 127 vid = tmp_vid; |
| 128 pid = tmp_pid; |
| 129 for (const auto& device : devices) { |
| 130 if (device.compare(value) == 0) { |
| 131 device_infos_[camera_id].usb_vid = vid; |
| 132 device_infos_[camera_id].usb_pid = pid; |
| 133 break; |
| 134 } |
| 135 } |
| 136 |
| 137 VLOG(1) << __func__ << ": Camera" << camera_id << " " << kUsbVidPid |
| 138 << ": " << value; |
| 139 } else if (!vid.empty() && !pid.empty()) { |
| 140 // Some characteristics are module-specific, so only matched ones are |
| 141 // selected. |
| 142 if (device_infos_[camera_id].usb_vid != vid || |
| 143 device_infos_[camera_id].usb_pid != pid) { |
| 144 VLOG(1) << __func__ << ": Mismatched module: " |
| 145 << "vid: " << vid << " pid: " << pid; |
| 146 continue; |
| 147 } |
| 148 AddPerModuleCharacteristic(camera_id, sub_keys[2], value); |
| 149 } else { |
| 150 // Characteristic usb_vid_pid should come before other module-specific |
| 151 // characteristics. |
| 152 LOG(ERROR) << __func__ << ": Illegal format." |
| 153 << " usb_vid_pid should come before: " << buffer; |
| 154 } |
| 155 } |
| 156 } |
| 157 base::CloseFile(file); |
| 158 return device_infos_; |
| 159 } |
| 160 |
| 161 int CameraCharacteristics::GetCameraFacing(const std::string& model_id) { |
| 162 std::vector<std::string> model_ids; |
| 163 model_ids.push_back(model_id); |
| 164 DeviceInfos device_infos = GetCharacteristicsFromFile(model_ids); |
| 165 for (auto device_info : device_infos) { |
| 166 char vid_pid[16]; |
| 167 sprintf(vid_pid, "%s:%s", device_info.usb_vid.c_str(), |
| 168 device_info.usb_pid.c_str()); |
| 169 if (strcmp(model_id.c_str(), vid_pid) == 0) { |
| 170 return device_info.lens_facing; |
| 171 } |
| 172 } |
| 173 return 0; |
| 174 } |
| 175 |
| 176 void CameraCharacteristics::AddPerCameraCharacteristic( |
| 177 uint32_t camera_id, |
| 178 const char* characteristic, |
| 179 const char* value) { |
| 180 if (strcmp(characteristic, kLensFacing) == 0) { |
| 181 VLOG(1) << __func__ << ": " << characteristic << ": " << value; |
| 182 device_infos_[camera_id].lens_facing = strtol(value, NULL, 10); |
| 183 } else if (strcmp(characteristic, kSensorOrientation) == 0) { |
| 184 VLOG(1) << __func__ << ": " << characteristic << ": " << value; |
| 185 device_infos_[camera_id].sensor_orientation = strtol(value, NULL, 10); |
| 186 } else { |
| 187 LOG(ERROR) << __func__ << ": Unknown characteristic: " << characteristic |
| 188 << " value: " << value; |
| 189 } |
| 190 } |
| 191 |
| 192 void CameraCharacteristics::AddPerModuleCharacteristic( |
| 193 uint32_t camera_id, |
| 194 const char* characteristic, |
| 195 const char* value) { |
| 196 if (strcmp(characteristic, kFramesToSkipAfterStreamon) == 0) { |
| 197 VLOG(1) << __func__ << ": " << characteristic << ": " << value; |
| 198 device_infos_[camera_id].frames_to_skip_after_streamon = |
| 199 strtol(value, NULL, 10); |
| 200 } else if (strcmp(characteristic, kHorizontalViewAngle_16_9) == 0) { |
| 201 AddFloatValue(value, kHorizontalViewAngle_16_9, |
| 202 &device_infos_[camera_id].horizontal_view_angle_16_9); |
| 203 } else if (strcmp(characteristic, kHorizontalViewAngle_4_3) == 0) { |
| 204 AddFloatValue(value, kHorizontalViewAngle_4_3, |
| 205 &device_infos_[camera_id].horizontal_view_angle_4_3); |
| 206 } else if (strcmp(characteristic, kLensInfoAvailableFocalLengths) == 0) { |
| 207 device_infos_[camera_id].lens_info_available_focal_lengths.clear(); |
| 208 char tmp_value[256]; |
| 209 strcpy(tmp_value, value); |
| 210 char* focal_length = strtok(tmp_value, ","); |
| 211 while (focal_length) { |
| 212 float tmp_focal_length = strtof(focal_length, NULL); |
| 213 if (tmp_focal_length != 0.0) { |
| 214 VLOG(1) << __func__ << ": " << characteristic << ": " |
| 215 << tmp_focal_length; |
| 216 device_infos_[camera_id].lens_info_available_focal_lengths.push_back( |
| 217 tmp_focal_length); |
| 218 } else { |
| 219 LOG(ERROR) << __func__ << ": Invalid " << characteristic << ": " |
| 220 << value; |
| 221 device_infos_[camera_id].lens_info_available_focal_lengths.clear(); |
| 222 device_infos_[camera_id].lens_info_available_focal_lengths.push_back( |
| 223 kDefaultCharacteristics.lens_info_available_focal_lengths[0]); |
| 224 break; |
| 225 } |
| 226 focal_length = strtok(NULL, ","); |
| 227 } |
| 228 } else if (strcmp(characteristic, kLensInfoMinimumFocusDistance) == 0) { |
| 229 AddFloatValue(value, kLensInfoMinimumFocusDistance, |
| 230 &device_infos_[camera_id].lens_info_minimum_focus_distance); |
| 231 } else if (strcmp(characteristic, kLensInfoOptimalFocusDistance) == 0) { |
| 232 AddFloatValue(value, kLensInfoOptimalFocusDistance, |
| 233 &device_infos_[camera_id].lens_info_optimal_focus_distance); |
| 234 } else if (strcmp(characteristic, kVerticalViewAngle_16_9) == 0) { |
| 235 AddFloatValue(value, kVerticalViewAngle_16_9, |
| 236 &device_infos_[camera_id].vertical_view_angle_16_9); |
| 237 } else if (strcmp(characteristic, kVerticalViewAngle_4_3) == 0) { |
| 238 AddFloatValue(value, kVerticalViewAngle_4_3, |
| 239 &device_infos_[camera_id].vertical_view_angle_4_3); |
| 240 } else if (strcmp(characteristic, kLensInfoAvailableApertures) == 0) { |
| 241 /* Do nothing. This is for hal v3 */ |
| 242 } else if (strcmp(characteristic, kSensorInfoPhysicalSize) == 0) { |
| 243 /* Do nothing. This is for hal v3 */ |
| 244 } else if (strcmp(characteristic, kSensorInfoPixelArraySize) == 0) { |
| 245 /* Do nothing. This is for hal v3 */ |
| 246 } else { |
| 247 LOG(ERROR) << __func__ << ": Unknown characteristic: " << characteristic |
| 248 << " value: " << value; |
| 249 } |
| 250 } |
| 251 |
| 252 void CameraCharacteristics::AddFloatValue(const char* value, |
| 253 const char* characteristic_name, |
| 254 float* characteristic) { |
| 255 float tmp_value = strtof(value, NULL); |
| 256 if (tmp_value != 0.0) { |
| 257 VLOG(1) << __func__ << ": " << characteristic_name << ": " << value; |
| 258 *characteristic = tmp_value; |
| 259 } else { |
| 260 LOG(ERROR) << __func__ << ": Invalid " << characteristic_name << ": " |
| 261 << value; |
| 262 } |
| 263 } |
| 264 |
| 265 } // namespace media |
| OLD | NEW |