| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/capture/video/linux/v4l2_capture_delegate.h" | 5 #include "media/capture/video/linux/v4l2_capture_delegate.h" |
| 6 | 6 |
| 7 #include <linux/version.h> | 7 #include <linux/version.h> |
| 8 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
| 9 #include <poll.h> | 9 #include <poll.h> |
| 10 #include <sys/fcntl.h> | 10 #include <sys/fcntl.h> |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 request_buffer->memory = V4L2_MEMORY_MMAP; | 115 request_buffer->memory = V4L2_MEMORY_MMAP; |
| 116 request_buffer->count = count; | 116 request_buffer->count = count; |
| 117 } | 117 } |
| 118 | 118 |
| 119 // Returns the input |fourcc| as a std::string four char representation. | 119 // Returns the input |fourcc| as a std::string four char representation. |
| 120 static std::string FourccToString(uint32_t fourcc) { | 120 static std::string FourccToString(uint32_t fourcc) { |
| 121 return base::StringPrintf("%c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF, | 121 return base::StringPrintf("%c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF, |
| 122 (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF); | 122 (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF); |
| 123 } | 123 } |
| 124 | 124 |
| 125 // Creates a mojom::RangePtr with the range of values (min, max, current) of the | 125 // Running ioctl() on some devices, especially shortly after (re)opening the |
| 126 // user control associated with |control_id|. Returns an empty Range otherwise. | 126 // device file descriptor or (re)starting streaming, can fail but works after |
| 127 // retrying (https://crbug.com/670262). |
| 128 // Returns false if the |request| ioctl fails too many times. |
| 129 static bool RunIoctl(int fd, int request, void* argp) { |
| 130 int num_retries = 0; |
| 131 for (; HANDLE_EINTR(ioctl(fd, request, argp)) < 0 && |
| 132 num_retries < kMaxIOCtrlRetries; |
| 133 ++num_retries) { |
| 134 DPLOG(WARNING) << "ioctl"; |
| 135 } |
| 136 DPLOG_IF(ERROR, num_retries != kMaxIOCtrlRetries); |
| 137 return num_retries != kMaxIOCtrlRetries; |
| 138 } |
| 139 |
| 140 // Creates a mojom::RangePtr with the (min, max, current, step) values of the |
| 141 // control associated with |control_id|. Returns an empty Range otherwise. |
| 127 static mojom::RangePtr RetrieveUserControlRange(int device_fd, int control_id) { | 142 static mojom::RangePtr RetrieveUserControlRange(int device_fd, int control_id) { |
| 128 mojom::RangePtr capability = mojom::Range::New(); | 143 mojom::RangePtr capability = mojom::Range::New(); |
| 129 | 144 |
| 130 v4l2_queryctrl range = {}; | 145 v4l2_queryctrl range = {}; |
| 131 range.id = control_id; | 146 range.id = control_id; |
| 132 range.type = V4L2_CTRL_TYPE_INTEGER; | 147 range.type = V4L2_CTRL_TYPE_INTEGER; |
| 133 if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range)) < 0) | 148 if (!RunIoctl(device_fd, VIDIOC_QUERYCTRL, &range)) |
| 134 return mojom::Range::New(); | 149 return mojom::Range::New(); |
| 135 capability->max = range.maximum; | 150 capability->max = range.maximum; |
| 136 capability->min = range.minimum; | 151 capability->min = range.minimum; |
| 137 capability->step = range.step; | 152 capability->step = range.step; |
| 138 | 153 |
| 139 v4l2_control current = {}; | 154 v4l2_control current = {}; |
| 140 current.id = control_id; | 155 current.id = control_id; |
| 141 if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_G_CTRL, ¤t)) < 0) | 156 if (!RunIoctl(device_fd, VIDIOC_G_CTRL, ¤t)) |
| 142 return mojom::Range::New(); | 157 return mojom::Range::New(); |
| 143 capability->current = current.value; | 158 capability->current = current.value; |
| 144 | 159 |
| 145 return capability; | 160 return capability; |
| 146 } | 161 } |
| 147 | 162 |
| 148 // Determines if |control_id| is special, i.e. controls another one's state. | 163 // Determines if |control_id| is special, i.e. controls another one's state. |
| 149 static bool IsSpecialControl(int control_id) { | 164 static bool IsSpecialControl(int control_id) { |
| 150 switch (control_id) { | 165 switch (control_id) { |
| 151 case V4L2_CID_AUTO_WHITE_BALANCE: | 166 case V4L2_CID_AUTO_WHITE_BALANCE: |
| 152 case V4L2_CID_EXPOSURE_AUTO: | 167 case V4L2_CID_EXPOSURE_AUTO: |
| 153 case V4L2_CID_EXPOSURE_AUTO_PRIORITY: | 168 case V4L2_CID_EXPOSURE_AUTO_PRIORITY: |
| 154 case V4L2_CID_FOCUS_AUTO: | 169 case V4L2_CID_FOCUS_AUTO: |
| 155 return true; | 170 return true; |
| 156 } | 171 } |
| 157 return false; | 172 return false; |
| 158 } | 173 } |
| 159 | 174 |
| 160 // Sets all user control to their default. Some controls are enabled by another | 175 // Sets all user control to their default. Some controls are enabled by another |
| 161 // flag, usually having the word "auto" in the name, see IsSpecialControl(). | 176 // flag, usually having the word "auto" in the name, see IsSpecialControl(). |
| 162 // These flags are preset beforehand, then set to their defaults individually | 177 // These flags are preset beforehand, then set to their defaults individually |
| 163 // afterwards. | 178 // afterwards. |
| 164 static void ResetUserAndCameraControlsToDefault(int device_fd) { | 179 static void ResetUserAndCameraControlsToDefault(int device_fd) { |
| 165 // Set V4L2_CID_AUTO_WHITE_BALANCE to false first. | 180 // Set V4L2_CID_AUTO_WHITE_BALANCE to false first. |
| 166 v4l2_control auto_white_balance = {}; | 181 v4l2_control auto_white_balance = {}; |
| 167 auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE; | 182 auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE; |
| 168 auto_white_balance.value = false; | 183 auto_white_balance.value = false; |
| 169 int num_retries = 0; | 184 if (!RunIoctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance)) |
| 170 // Setting up the first control right after stopping streaming seems | |
| 171 // not to the work the first time, so retry a few times. | |
| 172 for (; num_retries < kMaxIOCtrlRetries && | |
| 173 HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance)) < 0; | |
| 174 ++num_retries) { | |
| 175 DPLOG(WARNING) << "VIDIOC_S_CTRL"; | |
| 176 } | |
| 177 if (num_retries == kMaxIOCtrlRetries) { | |
| 178 DLOG(ERROR) << "Cannot access device controls"; | |
| 179 return; | 185 return; |
| 180 } | |
| 181 | 186 |
| 182 std::vector<struct v4l2_ext_control> special_camera_controls; | 187 std::vector<struct v4l2_ext_control> special_camera_controls; |
| 183 // Set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL. | 188 // Set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL. |
| 184 v4l2_ext_control auto_exposure = {}; | 189 v4l2_ext_control auto_exposure = {}; |
| 185 auto_exposure.id = V4L2_CID_EXPOSURE_AUTO; | 190 auto_exposure.id = V4L2_CID_EXPOSURE_AUTO; |
| 186 auto_exposure.value = V4L2_EXPOSURE_MANUAL; | 191 auto_exposure.value = V4L2_EXPOSURE_MANUAL; |
| 187 special_camera_controls.push_back(auto_exposure); | 192 special_camera_controls.push_back(auto_exposure); |
| 188 // Set V4L2_CID_EXPOSURE_AUTO_PRIORITY to false. | 193 // Set V4L2_CID_EXPOSURE_AUTO_PRIORITY to false. |
| 189 v4l2_ext_control priority_auto_exposure = {}; | 194 v4l2_ext_control priority_auto_exposure = {}; |
| 190 priority_auto_exposure.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY; | 195 priority_auto_exposure.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY; |
| (...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; | 786 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; |
| 782 return false; | 787 return false; |
| 783 } | 788 } |
| 784 start_ = static_cast<uint8_t*>(start); | 789 start_ = static_cast<uint8_t*>(start); |
| 785 length_ = buffer.length; | 790 length_ = buffer.length; |
| 786 payload_size_ = 0; | 791 payload_size_ = 0; |
| 787 return true; | 792 return true; |
| 788 } | 793 } |
| 789 | 794 |
| 790 } // namespace media | 795 } // namespace media |
| OLD | NEW |