You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
541 lines
22 KiB
541 lines
22 KiB
commit 74e41428503d16ff365bbfa93ca23332ce04215a
|
|
Author: Ilya Nikolaevskiy <ilnik@chromium.org>
|
|
Date: Wed Apr 5 16:16:22 2023 +0000
|
|
|
|
Revert "V4L2: media/capture: Use VIDIOC_S_EXT_CTRLS API correctly"
|
|
|
|
This reverts commit 4301563bdea1766779b5e032d2eb2ff19959fce3.
|
|
|
|
Reason for revert: Breaks test bot: crbug.com/1430699
|
|
|
|
Original change's description:
|
|
> V4L2: media/capture: Use VIDIOC_S_EXT_CTRLS API correctly
|
|
>
|
|
> This CL:
|
|
> - Uses the `which` struct v4l2_ext_controls field instead of
|
|
> the deprecated `ctrl_class` alias field.
|
|
> - Prefers the new style value of `V4L2_CTRL_WHICH_CUR_VAL` for that
|
|
> field instead of the old style value of the control class ID as long
|
|
> as the device supports the new style (detected on run-time).
|
|
> - Sets special controls only if they are supported. Trying to set
|
|
> an unsupported special control as part of a VIDIOC_S_EXT_CTRLS call
|
|
> causes the whole VIDIOC_S_EXT_CTRLS call to fail.
|
|
> - Fixes control iteration not to skip over the brightness control.
|
|
> - Skips permanently disabled and read-only controls.
|
|
> - Enables the corresponding test case.
|
|
>
|
|
> This fixes VIDIOC_S_EXT_CTRLS to work on new device drivers, too.
|
|
>
|
|
> API: https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/vidioc-g-ext-ctrls.html#c.V4L.v4l2_ext_controls
|
|
>
|
|
> Bug: 1421739, 732355
|
|
> Change-Id: I13593bb647fe664d70a3d8ed8d2789f77397aa40
|
|
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4324021
|
|
> Commit-Queue: Eero Hakkinen <eero.hakkinen@intel.com>
|
|
> Reviewed-by: Tomas Gunnarsson <tommi@chromium.org>
|
|
> Reviewed-by: Ilya Nikolaevskiy <ilnik@chromium.org>
|
|
> Cr-Commit-Position: refs/heads/main@{#1116416}
|
|
|
|
Bug: 1421739, 732355
|
|
Change-Id: I291b80009550f0c890b5203060d9283a4074af97
|
|
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4401592
|
|
Commit-Queue: Tomas Gunnarsson <tommi@chromium.org>
|
|
Auto-Submit: Ilya Nikolaevskiy <ilnik@chromium.org>
|
|
Reviewed-by: Tomas Gunnarsson <tommi@chromium.org>
|
|
Cr-Commit-Position: refs/heads/main@{#1126615}
|
|
|
|
diff --git a/media/capture/video/linux/v4l2_capture_delegate.cc b/media/capture/video/linux/v4l2_capture_delegate.cc
|
|
index 7efa2b1c2252c..864111f5c255e 100644
|
|
--- a/media/capture/video/linux/v4l2_capture_delegate.cc
|
|
+++ b/media/capture/video/linux/v4l2_capture_delegate.cc
|
|
@@ -138,6 +138,47 @@ int GetControllingSpecialControl(int control_id) {
|
|
return 0;
|
|
}
|
|
|
|
+// Determines if |control_id| is special, i.e. controls another one's state.
|
|
+bool IsSpecialControl(int control_id) {
|
|
+ switch (control_id) {
|
|
+ case V4L2_CID_AUTO_WHITE_BALANCE:
|
|
+ case V4L2_CID_EXPOSURE_AUTO:
|
|
+ case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
|
|
+ case V4L2_CID_FOCUS_AUTO:
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+// Determines if |control_id| should be skipped, https://crbug.com/697885.
|
|
+#if !defined(V4L2_CID_PAN_SPEED)
|
|
+#define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 32)
|
|
+#endif
|
|
+#if !defined(V4L2_CID_TILT_SPEED)
|
|
+#define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 33)
|
|
+#endif
|
|
+#if !defined(V4L2_CID_PANTILT_CMD)
|
|
+#define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE + 34)
|
|
+#endif
|
|
+bool IsBlockedControl(int control_id) {
|
|
+ switch (control_id) {
|
|
+ case V4L2_CID_PAN_RELATIVE:
|
|
+ case V4L2_CID_TILT_RELATIVE:
|
|
+ case V4L2_CID_PAN_RESET:
|
|
+ case V4L2_CID_TILT_RESET:
|
|
+ case V4L2_CID_PAN_ABSOLUTE:
|
|
+ case V4L2_CID_TILT_ABSOLUTE:
|
|
+ case V4L2_CID_ZOOM_ABSOLUTE:
|
|
+ case V4L2_CID_ZOOM_RELATIVE:
|
|
+ case V4L2_CID_ZOOM_CONTINUOUS:
|
|
+ case V4L2_CID_PAN_SPEED:
|
|
+ case V4L2_CID_TILT_SPEED:
|
|
+ case V4L2_CID_PANTILT_CMD:
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
bool IsNonEmptyRange(const mojom::RangePtr& range) {
|
|
return range->min < range->max;
|
|
}
|
|
@@ -211,49 +252,6 @@ std::vector<uint32_t> V4L2CaptureDelegate::GetListOfUsableFourCcs(
|
|
return supported_formats;
|
|
}
|
|
|
|
-// Determines if |control_id| is special, i.e. controls another one's state.
|
|
-// static
|
|
-bool V4L2CaptureDelegate::IsSpecialControl(int control_id) {
|
|
- switch (control_id) {
|
|
- case V4L2_CID_AUTO_WHITE_BALANCE:
|
|
- case V4L2_CID_EXPOSURE_AUTO:
|
|
- case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
|
|
- case V4L2_CID_FOCUS_AUTO:
|
|
- return true;
|
|
- }
|
|
- return false;
|
|
-}
|
|
-
|
|
-// Determines if |control_id| should be skipped, https://crbug.com/697885.
|
|
-#if !defined(V4L2_CID_PAN_SPEED)
|
|
-#define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 32)
|
|
-#endif
|
|
-#if !defined(V4L2_CID_TILT_SPEED)
|
|
-#define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 33)
|
|
-#endif
|
|
-#if !defined(V4L2_CID_PANTILT_CMD)
|
|
-#define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE + 34)
|
|
-#endif
|
|
-// static
|
|
-bool V4L2CaptureDelegate::IsBlockedControl(int control_id) {
|
|
- switch (control_id) {
|
|
- case V4L2_CID_PAN_RELATIVE:
|
|
- case V4L2_CID_TILT_RELATIVE:
|
|
- case V4L2_CID_PAN_RESET:
|
|
- case V4L2_CID_TILT_RESET:
|
|
- case V4L2_CID_PAN_ABSOLUTE:
|
|
- case V4L2_CID_TILT_ABSOLUTE:
|
|
- case V4L2_CID_ZOOM_ABSOLUTE:
|
|
- case V4L2_CID_ZOOM_RELATIVE:
|
|
- case V4L2_CID_ZOOM_CONTINUOUS:
|
|
- case V4L2_CID_PAN_SPEED:
|
|
- case V4L2_CID_TILT_SPEED:
|
|
- case V4L2_CID_PANTILT_CMD:
|
|
- return true;
|
|
- }
|
|
- return false;
|
|
-}
|
|
-
|
|
V4L2CaptureDelegate::V4L2CaptureDelegate(
|
|
V4L2CaptureDevice* v4l2,
|
|
const VideoCaptureDeviceDescriptor& device_descriptor,
|
|
@@ -830,89 +828,100 @@ mojom::RangePtr V4L2CaptureDelegate::RetrieveUserControlRange(int control_id) {
|
|
}
|
|
|
|
void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault() {
|
|
+ // Set V4L2_CID_AUTO_WHITE_BALANCE to false first.
|
|
+ v4l2_control auto_white_balance = {};
|
|
+ auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE;
|
|
+ auto_white_balance.value = false;
|
|
+ if (!RunIoctl(VIDIOC_S_CTRL, &auto_white_balance))
|
|
+ return;
|
|
+
|
|
+ std::vector<struct v4l2_ext_control> special_camera_controls;
|
|
+ // Set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL.
|
|
+ v4l2_ext_control auto_exposure = {};
|
|
+ auto_exposure.id = V4L2_CID_EXPOSURE_AUTO;
|
|
+ auto_exposure.value = V4L2_EXPOSURE_MANUAL;
|
|
+ special_camera_controls.push_back(auto_exposure);
|
|
+ // Set V4L2_CID_EXPOSURE_AUTO_PRIORITY to false.
|
|
+ v4l2_ext_control priority_auto_exposure = {};
|
|
+ priority_auto_exposure.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
|
|
+ priority_auto_exposure.value = false;
|
|
+ special_camera_controls.push_back(priority_auto_exposure);
|
|
+ // Set V4L2_CID_FOCUS_AUTO to false.
|
|
+ v4l2_ext_control auto_focus = {};
|
|
+ auto_focus.id = V4L2_CID_FOCUS_AUTO;
|
|
+ auto_focus.value = false;
|
|
+ special_camera_controls.push_back(auto_focus);
|
|
+
|
|
struct v4l2_ext_controls ext_controls = {};
|
|
- ext_controls.which = V4L2_CTRL_WHICH_CUR_VAL;
|
|
- ext_controls.count = 0;
|
|
- const bool use_modern_s_ext_ctrls =
|
|
- DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) == 0;
|
|
+ ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
|
|
+ ext_controls.count = special_camera_controls.size();
|
|
+ ext_controls.controls = special_camera_controls.data();
|
|
+ if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) < 0)
|
|
+ DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
|
|
|
|
for (const auto& control : kControls) {
|
|
std::vector<struct v4l2_ext_control> camera_controls;
|
|
- std::vector<struct v4l2_ext_control> manual_special_camera_controls;
|
|
- std::vector<struct v4l2_ext_control> special_camera_controls;
|
|
|
|
v4l2_queryctrl range = {};
|
|
- // Start right below the base so that the first next retrieved control ID
|
|
- // is always the first available control ID within the class even if that
|
|
- // control ID is equal to the base (V4L2_CID_BRIGHTNESS equals to
|
|
- // V4L2_CID_USER_BASE).
|
|
- range.id = (control.control_base - 1) | V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
+ range.id = control.control_base | V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
while (0 == DoIoctl(VIDIOC_QUERYCTRL, &range)) {
|
|
if (V4L2_CTRL_ID2CLASS(range.id) != V4L2_CTRL_ID2CLASS(control.class_id))
|
|
break;
|
|
-
|
|
- v4l2_ext_control ext_control = {};
|
|
- ext_control.id = range.id;
|
|
- ext_control.value = range.default_value;
|
|
-
|
|
- // Prepare to query for the next control as `range` is an in-out
|
|
- // parameter.
|
|
range.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
|
|
- if (range.flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_READ_ONLY)) {
|
|
- // Permanently disabled or permanently read-only.
|
|
+ if (IsSpecialControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
|
|
continue;
|
|
- }
|
|
- if (IsBlockedControl(ext_control.id)) {
|
|
+ if (IsBlockedControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
|
|
continue;
|
|
- }
|
|
|
|
- if (IsSpecialControl(ext_control.id)) {
|
|
- special_camera_controls.push_back(ext_control);
|
|
- if (ext_control.id == V4L2_CID_EXPOSURE_AUTO) {
|
|
- ext_control.value = V4L2_EXPOSURE_MANUAL;
|
|
- } else {
|
|
- ext_control.value = false; // Not automatic but manual.
|
|
- }
|
|
- manual_special_camera_controls.push_back(ext_control);
|
|
- } else {
|
|
- camera_controls.push_back(ext_control);
|
|
- }
|
|
+ struct v4l2_ext_control ext_control = {};
|
|
+ ext_control.id = range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
+ ext_control.value = range.default_value;
|
|
+ camera_controls.push_back(ext_control);
|
|
}
|
|
|
|
if (!camera_controls.empty()) {
|
|
- // Set special controls to manual modes first.
|
|
- if (!manual_special_camera_controls.empty()) {
|
|
- ext_controls.which =
|
|
- use_modern_s_ext_ctrls ? V4L2_CTRL_WHICH_CUR_VAL : control.class_id;
|
|
- ext_controls.count = manual_special_camera_controls.size();
|
|
- ext_controls.controls = manual_special_camera_controls.data();
|
|
- if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) < 0) {
|
|
- DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
|
|
- }
|
|
- }
|
|
-
|
|
- // Set non-special controls to the default values.
|
|
- ext_controls.which =
|
|
- use_modern_s_ext_ctrls ? V4L2_CTRL_WHICH_CUR_VAL : control.class_id;
|
|
- ext_controls.count = camera_controls.size();
|
|
- ext_controls.controls = camera_controls.data();
|
|
- if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) < 0) {
|
|
- DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
|
|
- }
|
|
- }
|
|
-
|
|
- // Set special controls to the default values.
|
|
- if (!special_camera_controls.empty()) {
|
|
- ext_controls.which =
|
|
- use_modern_s_ext_ctrls ? V4L2_CTRL_WHICH_CUR_VAL : control.class_id;
|
|
- ext_controls.count = special_camera_controls.size();
|
|
- ext_controls.controls = special_camera_controls.data();
|
|
- if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) < 0) {
|
|
+ struct v4l2_ext_controls ext_controls2 = {};
|
|
+ ext_controls2.ctrl_class = control.class_id;
|
|
+ ext_controls2.count = camera_controls.size();
|
|
+ ext_controls2.controls = camera_controls.data();
|
|
+ if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls2) < 0)
|
|
DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
|
|
- }
|
|
}
|
|
}
|
|
+
|
|
+ // Now set the special flags to the default values
|
|
+ v4l2_queryctrl range = {};
|
|
+ range.id = V4L2_CID_AUTO_WHITE_BALANCE;
|
|
+ DoIoctl(VIDIOC_QUERYCTRL, &range);
|
|
+ auto_white_balance.value = range.default_value;
|
|
+ DoIoctl(VIDIOC_S_CTRL, &auto_white_balance);
|
|
+
|
|
+ special_camera_controls.clear();
|
|
+ memset(&range, 0, sizeof(range));
|
|
+ range.id = V4L2_CID_EXPOSURE_AUTO;
|
|
+ DoIoctl(VIDIOC_QUERYCTRL, &range);
|
|
+ auto_exposure.value = range.default_value;
|
|
+ special_camera_controls.push_back(auto_exposure);
|
|
+
|
|
+ memset(&range, 0, sizeof(range));
|
|
+ range.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
|
|
+ DoIoctl(VIDIOC_QUERYCTRL, &range);
|
|
+ priority_auto_exposure.value = range.default_value;
|
|
+ special_camera_controls.push_back(priority_auto_exposure);
|
|
+
|
|
+ memset(&range, 0, sizeof(range));
|
|
+ range.id = V4L2_CID_FOCUS_AUTO;
|
|
+ DoIoctl(VIDIOC_QUERYCTRL, &range);
|
|
+ auto_focus.value = range.default_value;
|
|
+ special_camera_controls.push_back(auto_focus);
|
|
+
|
|
+ memset(&ext_controls, 0, sizeof(ext_controls));
|
|
+ ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
|
|
+ ext_controls.count = special_camera_controls.size();
|
|
+ ext_controls.controls = special_camera_controls.data();
|
|
+ if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) < 0)
|
|
+ DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
|
|
}
|
|
|
|
bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
|
|
diff --git a/media/capture/video/linux/v4l2_capture_delegate.h b/media/capture/video/linux/v4l2_capture_delegate.h
|
|
index 5eaa0cd004b81..c9be3d02f9344 100644
|
|
--- a/media/capture/video/linux/v4l2_capture_delegate.h
|
|
+++ b/media/capture/video/linux/v4l2_capture_delegate.h
|
|
@@ -78,9 +78,6 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final {
|
|
|
|
base::WeakPtr<V4L2CaptureDelegate> GetWeakPtr();
|
|
|
|
- static bool IsBlockedControl(int control_id);
|
|
- static bool IsSpecialControl(int control_id);
|
|
-
|
|
private:
|
|
friend class V4L2CaptureDelegateTest;
|
|
|
|
diff --git a/media/capture/video/linux/v4l2_capture_delegate_unittest.cc b/media/capture/video/linux/v4l2_capture_delegate_unittest.cc
|
|
index 06046ca45d634..4e6e38bbd5c72 100644
|
|
--- a/media/capture/video/linux/v4l2_capture_delegate_unittest.cc
|
|
+++ b/media/capture/video/linux/v4l2_capture_delegate_unittest.cc
|
|
@@ -35,110 +35,119 @@ static struct {
|
|
} const kControls[] = {{V4L2_CID_USER_BASE, V4L2_CID_USER_CLASS},
|
|
{V4L2_CID_CAMERA_CLASS_BASE, V4L2_CID_CAMERA_CLASS}};
|
|
|
|
+// Determines if |control_id| is special, i.e. controls another one's state, or
|
|
+// if it should be denied (see https://crbug.com/697885).
|
|
+#if !defined(V4L2_CID_PAN_SPEED)
|
|
+#define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 32)
|
|
+#endif
|
|
+#if !defined(V4L2_CID_TILT_SPEED)
|
|
+#define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 33)
|
|
+#endif
|
|
+#if !defined(V4L2_CID_PANTILT_CMD)
|
|
+#define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE + 34)
|
|
+#endif
|
|
+static bool IsSpecialOrBlockedControl(int control_id) {
|
|
+ switch (control_id) {
|
|
+ case V4L2_CID_AUTO_WHITE_BALANCE:
|
|
+ case V4L2_CID_EXPOSURE_AUTO:
|
|
+ case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
|
|
+ case V4L2_CID_FOCUS_AUTO:
|
|
+ case V4L2_CID_PAN_RELATIVE:
|
|
+ case V4L2_CID_TILT_RELATIVE:
|
|
+ case V4L2_CID_PAN_RESET:
|
|
+ case V4L2_CID_TILT_RESET:
|
|
+ case V4L2_CID_PAN_ABSOLUTE:
|
|
+ case V4L2_CID_TILT_ABSOLUTE:
|
|
+ case V4L2_CID_ZOOM_ABSOLUTE:
|
|
+ case V4L2_CID_ZOOM_RELATIVE:
|
|
+ case V4L2_CID_ZOOM_CONTINUOUS:
|
|
+ case V4L2_CID_PAN_SPEED:
|
|
+ case V4L2_CID_TILT_SPEED:
|
|
+ case V4L2_CID_PANTILT_CMD:
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
static void SetControlsToMaxValues(int device_fd) {
|
|
- v4l2_ext_controls ext_controls;
|
|
- memset(&ext_controls, 0, sizeof(ext_controls));
|
|
- ext_controls.which = V4L2_CTRL_WHICH_CUR_VAL;
|
|
- ext_controls.count = 0;
|
|
- const bool use_modern_s_ext_ctrls =
|
|
- HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) == 0;
|
|
+ // Set V4L2_CID_AUTO_WHITE_BALANCE to false first.
|
|
+ v4l2_control auto_white_balance = {};
|
|
+ auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE;
|
|
+ auto_white_balance.value = false;
|
|
+ if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance)) < 0)
|
|
+ DPLOG(ERROR) << "VIDIOC_S_CTRL";
|
|
+
|
|
+ std::vector<struct v4l2_ext_control> special_camera_controls;
|
|
+ // Set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL.
|
|
+ v4l2_ext_control auto_exposure = {};
|
|
+ auto_exposure.id = V4L2_CID_EXPOSURE_AUTO;
|
|
+ auto_exposure.value = V4L2_EXPOSURE_MANUAL;
|
|
+ special_camera_controls.push_back(auto_exposure);
|
|
+ // Set V4L2_CID_EXPOSURE_AUTO_PRIORITY to false.
|
|
+ v4l2_ext_control priority_auto_exposure = {};
|
|
+ priority_auto_exposure.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
|
|
+ priority_auto_exposure.value = false;
|
|
+ special_camera_controls.push_back(priority_auto_exposure);
|
|
+ // Set V4L2_CID_FOCUS_AUTO to false.
|
|
+ v4l2_ext_control auto_focus = {};
|
|
+ auto_focus.id = V4L2_CID_FOCUS_AUTO;
|
|
+ auto_focus.value = false;
|
|
+ special_camera_controls.push_back(auto_focus);
|
|
+
|
|
+ struct v4l2_ext_controls camera_ext_controls = {};
|
|
+ camera_ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
|
|
+ camera_ext_controls.count = special_camera_controls.size();
|
|
+ camera_ext_controls.controls = special_camera_controls.data();
|
|
+ if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &camera_ext_controls)) <
|
|
+ 0) {
|
|
+ DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
|
|
+ }
|
|
|
|
for (const auto& control : kControls) {
|
|
std::vector<struct v4l2_ext_control> camera_controls;
|
|
- std::vector<struct v4l2_ext_control> manual_special_camera_controls;
|
|
|
|
v4l2_queryctrl range = {};
|
|
- // Start right below the base so that the first next retrieved control ID
|
|
- // is always the first available control ID within the class even if that
|
|
- // control ID is equal to the base (V4L2_CID_BRIGHTNESS equals to
|
|
- // V4L2_CID_USER_BASE).
|
|
- range.id = (control.control_base - 1) | V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
+ range.id = control.control_base | V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
while (0 == HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range))) {
|
|
if (V4L2_CTRL_ID2CLASS(range.id) != V4L2_CTRL_ID2CLASS(control.class_id))
|
|
break;
|
|
-
|
|
- v4l2_ext_control ext_control = {};
|
|
- ext_control.id = range.id;
|
|
-
|
|
- // Prepare to query for the next control as `range` is an in-out
|
|
- // parameter.
|
|
range.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
|
|
- if (range.flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_READ_ONLY)) {
|
|
- // Permanently disabled or permanently read-only.
|
|
- continue;
|
|
- }
|
|
- if (V4L2CaptureDelegate::IsBlockedControl(ext_control.id)) {
|
|
+ if (IsSpecialOrBlockedControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
|
|
continue;
|
|
- }
|
|
-
|
|
- if (V4L2CaptureDelegate::IsSpecialControl(ext_control.id)) {
|
|
- if (ext_control.id == V4L2_CID_EXPOSURE_AUTO) {
|
|
- ext_control.value = V4L2_EXPOSURE_MANUAL;
|
|
- } else {
|
|
- ext_control.value = false; // Not automatic but manual.
|
|
- }
|
|
- manual_special_camera_controls.push_back(ext_control);
|
|
- DVLOG(1) << __func__ << " " << range.name << " set to manual";
|
|
- } else {
|
|
- ext_control.value = range.maximum;
|
|
- camera_controls.push_back(ext_control);
|
|
- DVLOG(1) << __func__ << " " << range.name << " set to "
|
|
- << range.maximum;
|
|
- }
|
|
- }
|
|
+ DVLOG(1) << __func__ << " " << range.name << " set to " << range.maximum;
|
|
|
|
- // Set special controls to manual modes.
|
|
- if (!manual_special_camera_controls.empty()) {
|
|
- ext_controls.which =
|
|
- use_modern_s_ext_ctrls ? V4L2_CTRL_WHICH_CUR_VAL : control.class_id;
|
|
- ext_controls.count = manual_special_camera_controls.size();
|
|
- ext_controls.controls = manual_special_camera_controls.data();
|
|
- if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) <
|
|
- 0) {
|
|
- DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
|
|
- }
|
|
+ struct v4l2_ext_control ext_control = {};
|
|
+ ext_control.id = range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
+ ext_control.value = range.maximum;
|
|
+ camera_controls.push_back(ext_control);
|
|
}
|
|
|
|
- // Set non-special controls to maximum values.
|
|
if (!camera_controls.empty()) {
|
|
- ext_controls.which =
|
|
- use_modern_s_ext_ctrls ? V4L2_CTRL_WHICH_CUR_VAL : control.class_id;
|
|
+ struct v4l2_ext_controls ext_controls = {};
|
|
+ ext_controls.ctrl_class = control.class_id;
|
|
ext_controls.count = camera_controls.size();
|
|
ext_controls.controls = camera_controls.data();
|
|
if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < 0)
|
|
DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
|
|
}
|
|
|
|
- // Start right below the base so that the first next retrieved control ID
|
|
- // is always the first available control ID within the class even if that
|
|
- // control ID is equal to the base (V4L2_CID_BRIGHTNESS equals to
|
|
- // V4L2_CID_USER_BASE).
|
|
- range.id = (control.control_base - 1) | V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
+ range.id = control.control_base | V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
while (0 == HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range))) {
|
|
if (V4L2_CTRL_ID2CLASS(range.id) != V4L2_CTRL_ID2CLASS(control.class_id))
|
|
break;
|
|
-
|
|
- v4l2_control readback = {};
|
|
- readback.id = range.id;
|
|
-
|
|
- // Prepare to query for the next control as `range` is an in-out
|
|
- // parameter.
|
|
range.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
|
|
- if (range.flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_READ_ONLY)) {
|
|
- // Permanently disabled or permanently read-only.
|
|
+ if (IsSpecialOrBlockedControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
|
|
continue;
|
|
- }
|
|
- if (V4L2CaptureDelegate::IsBlockedControl(readback.id) ||
|
|
- V4L2CaptureDelegate::IsSpecialControl(readback.id)) {
|
|
- continue;
|
|
- }
|
|
+ DVLOG(1) << __func__ << " " << range.name << " set to " << range.maximum;
|
|
|
|
+ v4l2_control readback = {};
|
|
+ readback.id = range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
|
|
if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_G_CTRL, &readback)) < 0)
|
|
DPLOG(ERROR) << range.name << ", failed to be read.";
|
|
- EXPECT_EQ(range.maximum, readback.value)
|
|
- << " control " << range.name << " didn't set correctly";
|
|
+ EXPECT_EQ(range.maximum, readback.value) << " control " << range.name
|
|
+ << " didnt set correctly";
|
|
}
|
|
}
|
|
}
|
|
@@ -186,7 +195,15 @@ class V4L2CaptureDelegateTest : public ::testing::Test {
|
|
|
|
} // anonymous namespace
|
|
|
|
-TEST_F(V4L2CaptureDelegateTest, CreateAndDestroyAndVerifyControls) {
|
|
+// Fails on Linux, see crbug/732355
|
|
+#if BUILDFLAG(IS_LINUX)
|
|
+#define MAYBE_CreateAndDestroyAndVerifyControls \
|
|
+ DISABLED_CreateAndDestroyAndVerifyControls
|
|
+#else
|
|
+#define MAYBE_CreateAndDestroyAndVerifyControls \
|
|
+ CreateAndDestroyAndVerifyControls
|
|
+#endif
|
|
+TEST_F(V4L2CaptureDelegateTest, MAYBE_CreateAndDestroyAndVerifyControls) {
|
|
// Check that there is at least a video device, otherwise bail.
|
|
const base::FilePath path("/dev/");
|
|
base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
|