Chromium Code Reviews| 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; | |
|
kcwu
2016/11/17 10:31:18
If parse failed, you will push_back a default valu
| |
| 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, "."); | |
|
kcwu
2016/11/17 10:31:19
Don't use strtok() because it keep internal state
| |
| 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 } | |
|
kcwu
2016/11/17 10:31:18
what if camera_id < device_infos_.size() ?
I'd pr
| |
| 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(), | |
|
kcwu
2016/11/17 10:31:19
I am wondering will this buffer overflow?
| |
| 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 DeviceInfo::LENS_FACING_UNKNOWN; | |
| 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) { | |
|
kcwu
2016/11/17 10:31:19
compare float value using "!=" ?
| |
| 257 VLOG(1) << __func__ << ": " << characteristic_name << ": " << value; | |
| 258 *characteristic = tmp_value; | |
| 259 } else { | |
| 260 LOG(ERROR) << __func__ << ": Invalid " << characteristic_name << ": " | |
|
kcwu
2016/11/17 10:31:18
I didn't check the detail. But reject 0 for this g
| |
| 261 << value; | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 } // namespace media | |
| OLD | NEW |