Commit 2d01c9a0 authored by Lei Zhang's avatar Lei Zhang Committed by Commit Bot

Add some DoIoctl() helpers in Linux video capture code.

Change-Id: If8bd9653c8ebaffa2d2bd50fad1c1f0a412a5c88
Reviewed-on: https://chromium-review.googlesource.com/1215052Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#590464}
parent 1dd87306
...@@ -268,11 +268,10 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -268,11 +268,10 @@ void V4L2CaptureDelegate::AllocateAndStart(
return; return;
} }
ResetUserAndCameraControlsToDefault(device_fd_.get()); ResetUserAndCameraControlsToDefault();
v4l2_capability cap = {}; v4l2_capability cap = {};
if (!((HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == if (!(DoIoctl(VIDIOC_QUERYCAP, &cap) == 0 &&
0) &&
((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)))) { !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)))) {
device_fd_.reset(); device_fd_.reset();
...@@ -289,11 +288,9 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -289,11 +288,9 @@ void V4L2CaptureDelegate::AllocateAndStart(
v4l2_fmtdesc fmtdesc = {}; v4l2_fmtdesc fmtdesc = {};
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (; HANDLE_EINTR( for (; DoIoctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index)
v4l2_->ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == 0;
++fmtdesc.index) {
best = std::find(desired_v4l2_formats.begin(), best, fmtdesc.pixelformat); best = std::find(desired_v4l2_formats.begin(), best, fmtdesc.pixelformat);
}
if (best == desired_v4l2_formats.end()) { if (best == desired_v4l2_formats.end()) {
SetErrorState(VideoCaptureError::kV4L2FailedToFindASupportedCameraFormat, SetErrorState(VideoCaptureError::kV4L2FailedToFindASupportedCameraFormat,
FROM_HERE, "Failed to find a supported camera format."); FROM_HERE, "Failed to find a supported camera format.");
...@@ -303,8 +300,7 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -303,8 +300,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
DVLOG(1) << "Chosen pixel format is " << FourccToString(*best); DVLOG(1) << "Chosen pixel format is " << FourccToString(*best);
FillV4L2Format(&video_fmt_, width, height, *best); FillV4L2Format(&video_fmt_, width, height, *best);
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt_)) < if (DoIoctl(VIDIOC_S_FMT, &video_fmt_) < 0) {
0) {
SetErrorState(VideoCaptureError::kV4L2FailedToSetVideoCaptureFormat, SetErrorState(VideoCaptureError::kV4L2FailedToSetVideoCaptureFormat,
FROM_HERE, "Failed to set video capture format"); FROM_HERE, "Failed to set video capture format");
return; return;
...@@ -321,8 +317,7 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -321,8 +317,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
v4l2_streamparm streamparm = {}; v4l2_streamparm streamparm = {};
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
// The following line checks that the driver knows about framerate get/set. // The following line checks that the driver knows about framerate get/set.
if (HANDLE_EINTR( if (DoIoctl(VIDIOC_G_PARM, &streamparm) >= 0) {
v4l2_->ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) {
// Now check if the device is able to accept a capture framerate set. // Now check if the device is able to accept a capture framerate set.
if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) { if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
// |frame_rate| is float, approximate by a fraction. // |frame_rate| is float, approximate by a fraction.
...@@ -331,8 +326,7 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -331,8 +326,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
(frame_rate) ? (frame_rate * kFrameRatePrecision) (frame_rate) ? (frame_rate * kFrameRatePrecision)
: (kTypicalFramerate * kFrameRatePrecision); : (kTypicalFramerate * kFrameRatePrecision);
if (HANDLE_EINTR( if (DoIoctl(VIDIOC_S_PARM, &streamparm) < 0) {
v4l2_->ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < 0) {
SetErrorState(VideoCaptureError::kV4L2FailedToSetCameraFramerate, SetErrorState(VideoCaptureError::kV4L2FailedToSetCameraFramerate,
FROM_HERE, "Failed to set camera framerate"); FROM_HERE, "Failed to set camera framerate");
return; return;
...@@ -353,8 +347,7 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -353,8 +347,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
struct v4l2_control control = {}; struct v4l2_control control = {};
control.id = V4L2_CID_POWER_LINE_FREQUENCY; control.id = V4L2_CID_POWER_LINE_FREQUENCY;
control.value = power_line_frequency_; control.value = power_line_frequency_;
const int retval = const int retval = DoIoctl(VIDIOC_S_CTRL, &control);
HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &control));
if (retval != 0) if (retval != 0)
DVLOG(1) << "Error setting power line frequency removal"; DVLOG(1) << "Error setting power line frequency removal";
} }
...@@ -366,8 +359,7 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -366,8 +359,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
v4l2_requestbuffers r_buffer; v4l2_requestbuffers r_buffer;
FillV4L2RequestBuffer(&r_buffer, kNumVideoBuffers); FillV4L2RequestBuffer(&r_buffer, kNumVideoBuffers);
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < if (DoIoctl(VIDIOC_REQBUFS, &r_buffer) < 0) {
0) {
SetErrorState(VideoCaptureError::kV4L2ErrorRequestingMmapBuffers, FROM_HERE, SetErrorState(VideoCaptureError::kV4L2ErrorRequestingMmapBuffers, FROM_HERE,
"Error requesting MMAP buffers from V4L2"); "Error requesting MMAP buffers from V4L2");
return; return;
...@@ -381,8 +373,7 @@ void V4L2CaptureDelegate::AllocateAndStart( ...@@ -381,8 +373,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
} }
v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (HANDLE_EINTR( if (DoIoctl(VIDIOC_STREAMON, &capture_type) < 0) {
v4l2_->ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type)) < 0) {
SetErrorState(VideoCaptureError::kV4L2VidiocStreamonFailed, FROM_HERE, SetErrorState(VideoCaptureError::kV4L2VidiocStreamonFailed, FROM_HERE,
"VIDIOC_STREAMON failed"); "VIDIOC_STREAMON failed");
return; return;
...@@ -401,8 +392,7 @@ void V4L2CaptureDelegate::StopAndDeAllocate() { ...@@ -401,8 +392,7 @@ void V4L2CaptureDelegate::StopAndDeAllocate() {
// The order is important: stop streaming, clear |buffer_pool_|, // The order is important: stop streaming, clear |buffer_pool_|,
// thus munmap()ing the v4l2_buffers, and then return them to the OS. // thus munmap()ing the v4l2_buffers, and then return them to the OS.
v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_STREAMOFF, if (DoIoctl(VIDIOC_STREAMOFF, &capture_type) < 0) {
&capture_type)) < 0) {
SetErrorState(VideoCaptureError::kV4L2VidiocStreamoffFailed, FROM_HERE, SetErrorState(VideoCaptureError::kV4L2VidiocStreamoffFailed, FROM_HERE,
"VIDIOC_STREAMOFF failed"); "VIDIOC_STREAMOFF failed");
return; return;
...@@ -412,10 +402,10 @@ void V4L2CaptureDelegate::StopAndDeAllocate() { ...@@ -412,10 +402,10 @@ void V4L2CaptureDelegate::StopAndDeAllocate() {
v4l2_requestbuffers r_buffer; v4l2_requestbuffers r_buffer;
FillV4L2RequestBuffer(&r_buffer, 0); FillV4L2RequestBuffer(&r_buffer, 0);
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < if (DoIoctl(VIDIOC_REQBUFS, &r_buffer) < 0) {
0)
SetErrorState(VideoCaptureError::kV4L2FailedToVidiocReqbufsWithCount0, SetErrorState(VideoCaptureError::kV4L2FailedToVidiocReqbufsWithCount0,
FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0"); FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0");
}
// At this point we can close the device. // At this point we can close the device.
// This is also needed for correctly changing settings later via VIDIOC_S_FMT. // This is also needed for correctly changing settings later via VIDIOC_S_FMT.
...@@ -438,17 +428,16 @@ void V4L2CaptureDelegate::GetPhotoState( ...@@ -438,17 +428,16 @@ void V4L2CaptureDelegate::GetPhotoState(
mojom::PhotoStatePtr photo_capabilities = mojom::PhotoState::New(); mojom::PhotoStatePtr photo_capabilities = mojom::PhotoState::New();
photo_capabilities->zoom = photo_capabilities->zoom = RetrieveUserControlRange(V4L2_CID_ZOOM_ABSOLUTE);
RetrieveUserControlRange(device_fd_.get(), V4L2_CID_ZOOM_ABSOLUTE);
v4l2_queryctrl manual_focus_ctrl = {}; v4l2_queryctrl manual_focus_ctrl = {};
manual_focus_ctrl.id = V4L2_CID_FOCUS_ABSOLUTE; manual_focus_ctrl.id = V4L2_CID_FOCUS_ABSOLUTE;
if (RunIoctl(device_fd_.get(), VIDIOC_QUERYCTRL, &manual_focus_ctrl)) if (RunIoctl(VIDIOC_QUERYCTRL, &manual_focus_ctrl))
photo_capabilities->supported_focus_modes.push_back(MeteringMode::MANUAL); photo_capabilities->supported_focus_modes.push_back(MeteringMode::MANUAL);
v4l2_queryctrl auto_focus_ctrl = {}; v4l2_queryctrl auto_focus_ctrl = {};
auto_focus_ctrl.id = V4L2_CID_FOCUS_AUTO; auto_focus_ctrl.id = V4L2_CID_FOCUS_AUTO;
if (RunIoctl(device_fd_.get(), VIDIOC_QUERYCTRL, &auto_focus_ctrl)) { if (RunIoctl(VIDIOC_QUERYCTRL, &auto_focus_ctrl)) {
photo_capabilities->supported_focus_modes.push_back( photo_capabilities->supported_focus_modes.push_back(
MeteringMode::CONTINUOUS); MeteringMode::CONTINUOUS);
} }
...@@ -456,19 +445,18 @@ void V4L2CaptureDelegate::GetPhotoState( ...@@ -456,19 +445,18 @@ void V4L2CaptureDelegate::GetPhotoState(
photo_capabilities->current_focus_mode = MeteringMode::NONE; photo_capabilities->current_focus_mode = MeteringMode::NONE;
v4l2_control auto_focus_current = {}; v4l2_control auto_focus_current = {};
auto_focus_current.id = V4L2_CID_FOCUS_AUTO; auto_focus_current.id = V4L2_CID_FOCUS_AUTO;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL, if (DoIoctl(VIDIOC_G_CTRL, &auto_focus_current) >= 0) {
&auto_focus_current)) >= 0) {
photo_capabilities->current_focus_mode = auto_focus_current.value photo_capabilities->current_focus_mode = auto_focus_current.value
? MeteringMode::CONTINUOUS ? MeteringMode::CONTINUOUS
: MeteringMode::MANUAL; : MeteringMode::MANUAL;
} }
photo_capabilities->focus_distance = photo_capabilities->focus_distance =
RetrieveUserControlRange(device_fd_.get(), V4L2_CID_FOCUS_ABSOLUTE); RetrieveUserControlRange(V4L2_CID_FOCUS_ABSOLUTE);
v4l2_queryctrl auto_exposure_ctrl = {}; v4l2_queryctrl auto_exposure_ctrl = {};
auto_exposure_ctrl.id = V4L2_CID_EXPOSURE_AUTO; auto_exposure_ctrl.id = V4L2_CID_EXPOSURE_AUTO;
if (RunIoctl(device_fd_.get(), VIDIOC_QUERYCTRL, &auto_exposure_ctrl)) { if (RunIoctl(VIDIOC_QUERYCTRL, &auto_exposure_ctrl)) {
photo_capabilities->supported_exposure_modes.push_back( photo_capabilities->supported_exposure_modes.push_back(
MeteringMode::MANUAL); MeteringMode::MANUAL);
photo_capabilities->supported_exposure_modes.push_back( photo_capabilities->supported_exposure_modes.push_back(
...@@ -478,8 +466,7 @@ void V4L2CaptureDelegate::GetPhotoState( ...@@ -478,8 +466,7 @@ void V4L2CaptureDelegate::GetPhotoState(
photo_capabilities->current_exposure_mode = MeteringMode::NONE; photo_capabilities->current_exposure_mode = MeteringMode::NONE;
v4l2_control exposure_current = {}; v4l2_control exposure_current = {};
exposure_current.id = V4L2_CID_EXPOSURE_AUTO; exposure_current.id = V4L2_CID_EXPOSURE_AUTO;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL, if (DoIoctl(VIDIOC_G_CTRL, &exposure_current) >= 0) {
&exposure_current)) >= 0) {
photo_capabilities->current_exposure_mode = photo_capabilities->current_exposure_mode =
exposure_current.value == V4L2_EXPOSURE_MANUAL exposure_current.value == V4L2_EXPOSURE_MANUAL
? MeteringMode::MANUAL ? MeteringMode::MANUAL
...@@ -487,10 +474,10 @@ void V4L2CaptureDelegate::GetPhotoState( ...@@ -487,10 +474,10 @@ void V4L2CaptureDelegate::GetPhotoState(
} }
photo_capabilities->exposure_compensation = photo_capabilities->exposure_compensation =
RetrieveUserControlRange(device_fd_.get(), V4L2_CID_EXPOSURE_ABSOLUTE); RetrieveUserControlRange(V4L2_CID_EXPOSURE_ABSOLUTE);
photo_capabilities->color_temperature = RetrieveUserControlRange( photo_capabilities->color_temperature =
device_fd_.get(), V4L2_CID_WHITE_BALANCE_TEMPERATURE); RetrieveUserControlRange(V4L2_CID_WHITE_BALANCE_TEMPERATURE);
if (photo_capabilities->color_temperature) { if (photo_capabilities->color_temperature) {
photo_capabilities->supported_white_balance_modes.push_back( photo_capabilities->supported_white_balance_modes.push_back(
MeteringMode::MANUAL); MeteringMode::MANUAL);
...@@ -498,7 +485,7 @@ void V4L2CaptureDelegate::GetPhotoState( ...@@ -498,7 +485,7 @@ void V4L2CaptureDelegate::GetPhotoState(
v4l2_queryctrl white_balance_ctrl = {}; v4l2_queryctrl white_balance_ctrl = {};
white_balance_ctrl.id = V4L2_CID_AUTO_WHITE_BALANCE; white_balance_ctrl.id = V4L2_CID_AUTO_WHITE_BALANCE;
if (RunIoctl(device_fd_.get(), VIDIOC_QUERYCTRL, &white_balance_ctrl)) { if (RunIoctl(VIDIOC_QUERYCTRL, &white_balance_ctrl)) {
photo_capabilities->supported_white_balance_modes.push_back( photo_capabilities->supported_white_balance_modes.push_back(
MeteringMode::CONTINUOUS); MeteringMode::CONTINUOUS);
} }
...@@ -506,8 +493,7 @@ void V4L2CaptureDelegate::GetPhotoState( ...@@ -506,8 +493,7 @@ void V4L2CaptureDelegate::GetPhotoState(
photo_capabilities->current_white_balance_mode = MeteringMode::NONE; photo_capabilities->current_white_balance_mode = MeteringMode::NONE;
v4l2_control white_balance_current = {}; v4l2_control white_balance_current = {};
white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE; white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL, if (DoIoctl(VIDIOC_G_CTRL, &white_balance_current) >= 0) {
&white_balance_current)) >= 0) {
photo_capabilities->current_white_balance_mode = photo_capabilities->current_white_balance_mode =
white_balance_current.value ? MeteringMode::CONTINUOUS white_balance_current.value ? MeteringMode::CONTINUOUS
: MeteringMode::MANUAL; : MeteringMode::MANUAL;
...@@ -524,13 +510,11 @@ void V4L2CaptureDelegate::GetPhotoState( ...@@ -524,13 +510,11 @@ void V4L2CaptureDelegate::GetPhotoState(
photo_capabilities->torch = false; photo_capabilities->torch = false;
photo_capabilities->brightness = photo_capabilities->brightness =
RetrieveUserControlRange(device_fd_.get(), V4L2_CID_BRIGHTNESS); RetrieveUserControlRange(V4L2_CID_BRIGHTNESS);
photo_capabilities->contrast = photo_capabilities->contrast = RetrieveUserControlRange(V4L2_CID_CONTRAST);
RetrieveUserControlRange(device_fd_.get(), V4L2_CID_CONTRAST);
photo_capabilities->saturation = photo_capabilities->saturation =
RetrieveUserControlRange(device_fd_.get(), V4L2_CID_SATURATION); RetrieveUserControlRange(V4L2_CID_SATURATION);
photo_capabilities->sharpness = photo_capabilities->sharpness = RetrieveUserControlRange(V4L2_CID_SHARPNESS);
RetrieveUserControlRange(device_fd_.get(), V4L2_CID_SHARPNESS);
std::move(callback).Run(std::move(photo_capabilities)); std::move(callback).Run(std::move(photo_capabilities));
} }
...@@ -546,8 +530,7 @@ void V4L2CaptureDelegate::SetPhotoOptions( ...@@ -546,8 +530,7 @@ void V4L2CaptureDelegate::SetPhotoOptions(
v4l2_control zoom_current = {}; v4l2_control zoom_current = {};
zoom_current.id = V4L2_CID_ZOOM_ABSOLUTE; zoom_current.id = V4L2_CID_ZOOM_ABSOLUTE;
zoom_current.value = settings->zoom; zoom_current.value = settings->zoom;
if (HANDLE_EINTR( if (DoIoctl(VIDIOC_S_CTRL, &zoom_current) < 0)
v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &zoom_current)) < 0)
DPLOG(ERROR) << "setting zoom to " << settings->zoom; DPLOG(ERROR) << "setting zoom to " << settings->zoom;
} }
...@@ -556,8 +539,7 @@ void V4L2CaptureDelegate::SetPhotoOptions( ...@@ -556,8 +539,7 @@ void V4L2CaptureDelegate::SetPhotoOptions(
v4l2_control set_focus_distance_ctrl = {}; v4l2_control set_focus_distance_ctrl = {};
set_focus_distance_ctrl.id = V4L2_CID_FOCUS_ABSOLUTE; set_focus_distance_ctrl.id = V4L2_CID_FOCUS_ABSOLUTE;
set_focus_distance_ctrl.value = settings->focus_distance; set_focus_distance_ctrl.value = settings->focus_distance;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, if (DoIoctl(VIDIOC_S_CTRL, &set_focus_distance_ctrl) < 0)
&set_focus_distance_ctrl)) < 0)
DPLOG(ERROR) << "setting focus distance to " << settings->focus_distance; DPLOG(ERROR) << "setting focus distance to " << settings->focus_distance;
} }
...@@ -568,22 +550,19 @@ void V4L2CaptureDelegate::SetPhotoOptions( ...@@ -568,22 +550,19 @@ void V4L2CaptureDelegate::SetPhotoOptions(
white_balance_set.id = V4L2_CID_AUTO_WHITE_BALANCE; white_balance_set.id = V4L2_CID_AUTO_WHITE_BALANCE;
white_balance_set.value = white_balance_set.value =
settings->white_balance_mode == mojom::MeteringMode::CONTINUOUS; settings->white_balance_mode == mojom::MeteringMode::CONTINUOUS;
HANDLE_EINTR( DoIoctl(VIDIOC_S_CTRL, &white_balance_set);
v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &white_balance_set));
} }
if (settings->has_color_temperature) { if (settings->has_color_temperature) {
v4l2_control auto_white_balance_current = {}; v4l2_control auto_white_balance_current = {};
auto_white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE; auto_white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE;
const int result = HANDLE_EINTR(v4l2_->ioctl( const int result = DoIoctl(VIDIOC_G_CTRL, &auto_white_balance_current);
device_fd_.get(), VIDIOC_G_CTRL, &auto_white_balance_current));
// Color temperature can only be applied if Auto White Balance is off. // Color temperature can only be applied if Auto White Balance is off.
if (result >= 0 && !auto_white_balance_current.value) { if (result >= 0 && !auto_white_balance_current.value) {
v4l2_control set_temperature = {}; v4l2_control set_temperature = {};
set_temperature.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; set_temperature.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
set_temperature.value = settings->color_temperature; set_temperature.value = settings->color_temperature;
HANDLE_EINTR( DoIoctl(VIDIOC_S_CTRL, &set_temperature);
v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_temperature));
} }
} }
...@@ -596,22 +575,19 @@ void V4L2CaptureDelegate::SetPhotoOptions( ...@@ -596,22 +575,19 @@ void V4L2CaptureDelegate::SetPhotoOptions(
settings->exposure_mode == mojom::MeteringMode::CONTINUOUS settings->exposure_mode == mojom::MeteringMode::CONTINUOUS
? V4L2_EXPOSURE_APERTURE_PRIORITY ? V4L2_EXPOSURE_APERTURE_PRIORITY
: V4L2_EXPOSURE_MANUAL; : V4L2_EXPOSURE_MANUAL;
HANDLE_EINTR( DoIoctl(VIDIOC_S_CTRL, &exposure_mode_set);
v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &exposure_mode_set));
} }
if (settings->has_exposure_compensation) { if (settings->has_exposure_compensation) {
v4l2_control auto_exposure_current = {}; v4l2_control auto_exposure_current = {};
auto_exposure_current.id = V4L2_CID_EXPOSURE_AUTO; auto_exposure_current.id = V4L2_CID_EXPOSURE_AUTO;
const int result = HANDLE_EINTR( const int result = DoIoctl(VIDIOC_G_CTRL, &auto_exposure_current);
v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_exposure_current));
// Exposure Compensation can only be applied if Auto Exposure is off. // Exposure Compensation can only be applied if Auto Exposure is off.
if (result >= 0 && auto_exposure_current.value == V4L2_EXPOSURE_MANUAL) { if (result >= 0 && auto_exposure_current.value == V4L2_EXPOSURE_MANUAL) {
v4l2_control set_exposure = {}; v4l2_control set_exposure = {};
set_exposure.id = V4L2_CID_EXPOSURE_ABSOLUTE; set_exposure.id = V4L2_CID_EXPOSURE_ABSOLUTE;
set_exposure.value = settings->exposure_compensation; set_exposure.value = settings->exposure_compensation;
HANDLE_EINTR( DoIoctl(VIDIOC_S_CTRL, &set_exposure);
v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_exposure));
} }
} }
...@@ -619,32 +595,28 @@ void V4L2CaptureDelegate::SetPhotoOptions( ...@@ -619,32 +595,28 @@ void V4L2CaptureDelegate::SetPhotoOptions(
v4l2_control current = {}; v4l2_control current = {};
current.id = V4L2_CID_BRIGHTNESS; current.id = V4L2_CID_BRIGHTNESS;
current.value = settings->brightness; current.value = settings->brightness;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < if (DoIoctl(VIDIOC_S_CTRL, &current) < 0)
0)
DPLOG(ERROR) << "setting brightness to " << settings->brightness; DPLOG(ERROR) << "setting brightness to " << settings->brightness;
} }
if (settings->has_contrast) { if (settings->has_contrast) {
v4l2_control current = {}; v4l2_control current = {};
current.id = V4L2_CID_CONTRAST; current.id = V4L2_CID_CONTRAST;
current.value = settings->contrast; current.value = settings->contrast;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < if (DoIoctl(VIDIOC_S_CTRL, &current) < 0)
0)
DPLOG(ERROR) << "setting contrast to " << settings->contrast; DPLOG(ERROR) << "setting contrast to " << settings->contrast;
} }
if (settings->has_saturation) { if (settings->has_saturation) {
v4l2_control current = {}; v4l2_control current = {};
current.id = V4L2_CID_SATURATION; current.id = V4L2_CID_SATURATION;
current.value = settings->saturation; current.value = settings->saturation;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < if (DoIoctl(VIDIOC_S_CTRL, &current) < 0)
0)
DPLOG(ERROR) << "setting saturation to " << settings->saturation; DPLOG(ERROR) << "setting saturation to " << settings->saturation;
} }
if (settings->has_sharpness) { if (settings->has_sharpness) {
v4l2_control current = {}; v4l2_control current = {};
current.id = V4L2_CID_SHARPNESS; current.id = V4L2_CID_SHARPNESS;
current.value = settings->sharpness; current.value = settings->sharpness;
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < if (DoIoctl(VIDIOC_S_CTRL, &current) < 0)
0)
DPLOG(ERROR) << "setting sharpness to " << settings->sharpness; DPLOG(ERROR) << "setting sharpness to " << settings->sharpness;
} }
...@@ -665,14 +637,9 @@ base::WeakPtr<V4L2CaptureDelegate> V4L2CaptureDelegate::GetWeakPtr() { ...@@ -665,14 +637,9 @@ base::WeakPtr<V4L2CaptureDelegate> V4L2CaptureDelegate::GetWeakPtr() {
V4L2CaptureDelegate::~V4L2CaptureDelegate() = default; V4L2CaptureDelegate::~V4L2CaptureDelegate() = default;
// Running v4l2_->ioctl() on some devices, especially shortly after (re)opening bool V4L2CaptureDelegate::RunIoctl(int request, void* argp) {
// the device file descriptor or (re)starting streaming, can fail but works
// after retrying (https://crbug.com/670262). Returns false if the |request|
// ioctl fails too many times.
bool V4L2CaptureDelegate::RunIoctl(int fd, int request, void* argp) {
int num_retries = 0; int num_retries = 0;
for (; HANDLE_EINTR(v4l2_->ioctl(fd, request, argp)) < 0 && for (; DoIoctl(request, argp) < 0 && num_retries < kMaxIOCtrlRetries;
num_retries < kMaxIOCtrlRetries;
++num_retries) { ++num_retries) {
DPLOG(WARNING) << "ioctl"; DPLOG(WARNING) << "ioctl";
} }
...@@ -680,16 +647,17 @@ bool V4L2CaptureDelegate::RunIoctl(int fd, int request, void* argp) { ...@@ -680,16 +647,17 @@ bool V4L2CaptureDelegate::RunIoctl(int fd, int request, void* argp) {
return num_retries != kMaxIOCtrlRetries; return num_retries != kMaxIOCtrlRetries;
} }
// Creates a mojom::RangePtr with the (min, max, current, step) values of the int V4L2CaptureDelegate::DoIoctl(int request, void* argp) {
// control associated with |control_id|. Returns an empty Range otherwise. return HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), request, argp));
mojom::RangePtr V4L2CaptureDelegate::RetrieveUserControlRange(int device_fd, }
int control_id) {
mojom::RangePtr V4L2CaptureDelegate::RetrieveUserControlRange(int control_id) {
mojom::RangePtr capability = mojom::Range::New(); mojom::RangePtr capability = mojom::Range::New();
v4l2_queryctrl range = {}; v4l2_queryctrl range = {};
range.id = control_id; range.id = control_id;
range.type = V4L2_CTRL_TYPE_INTEGER; range.type = V4L2_CTRL_TYPE_INTEGER;
if (!RunIoctl(device_fd, VIDIOC_QUERYCTRL, &range)) if (!RunIoctl(VIDIOC_QUERYCTRL, &range))
return mojom::Range::New(); return mojom::Range::New();
capability->max = range.maximum; capability->max = range.maximum;
capability->min = range.minimum; capability->min = range.minimum;
...@@ -697,23 +665,19 @@ mojom::RangePtr V4L2CaptureDelegate::RetrieveUserControlRange(int device_fd, ...@@ -697,23 +665,19 @@ mojom::RangePtr V4L2CaptureDelegate::RetrieveUserControlRange(int device_fd,
v4l2_control current = {}; v4l2_control current = {};
current.id = control_id; current.id = control_id;
if (!RunIoctl(device_fd, VIDIOC_G_CTRL, &current)) if (!RunIoctl(VIDIOC_G_CTRL, &current))
return mojom::Range::New(); return mojom::Range::New();
capability->current = current.value; capability->current = current.value;
return capability; return capability;
} }
// Sets all user control to their default. Some controls are enabled by another void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault() {
// flag, usually having the word "auto" in the name, see IsSpecialControl().
// These flags are preset beforehand, then set to their defaults individually
// afterwards.
void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) {
// Set V4L2_CID_AUTO_WHITE_BALANCE to false first. // Set V4L2_CID_AUTO_WHITE_BALANCE to false first.
v4l2_control auto_white_balance = {}; v4l2_control auto_white_balance = {};
auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE; auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE;
auto_white_balance.value = false; auto_white_balance.value = false;
if (!RunIoctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance)) if (!RunIoctl(VIDIOC_S_CTRL, &auto_white_balance))
return; return;
std::vector<struct v4l2_ext_control> special_camera_controls; std::vector<struct v4l2_ext_control> special_camera_controls;
...@@ -737,8 +701,7 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) { ...@@ -737,8 +701,7 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) {
ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS; ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
ext_controls.count = special_camera_controls.size(); ext_controls.count = special_camera_controls.size();
ext_controls.controls = special_camera_controls.data(); ext_controls.controls = special_camera_controls.data();
if (HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) < 0)
0)
DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS"; DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
std::vector<struct v4l2_ext_control> camera_controls; std::vector<struct v4l2_ext_control> camera_controls;
...@@ -747,8 +710,7 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) { ...@@ -747,8 +710,7 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) {
v4l2_queryctrl range = {}; v4l2_queryctrl range = {};
range.id = control.control_base | V4L2_CTRL_FLAG_NEXT_CTRL; range.id = control.control_base | V4L2_CTRL_FLAG_NEXT_CTRL;
while (0 == while (0 == DoIoctl(VIDIOC_QUERYCTRL, &range)) {
HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range))) {
if (V4L2_CTRL_ID2CLASS(range.id) != V4L2_CTRL_ID2CLASS(control.class_id)) if (V4L2_CTRL_ID2CLASS(range.id) != V4L2_CTRL_ID2CLASS(control.class_id))
break; break;
range.id |= V4L2_CTRL_FLAG_NEXT_CTRL; range.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
...@@ -765,12 +727,11 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) { ...@@ -765,12 +727,11 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) {
} }
if (!camera_controls.empty()) { if (!camera_controls.empty()) {
struct v4l2_ext_controls ext_controls = {}; struct v4l2_ext_controls ext_controls2 = {};
ext_controls.ctrl_class = control.class_id; ext_controls2.ctrl_class = control.class_id;
ext_controls.count = camera_controls.size(); ext_controls2.count = camera_controls.size();
ext_controls.controls = camera_controls.data(); ext_controls2.controls = camera_controls.data();
if (HANDLE_EINTR( if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls2) < 0)
v4l2_->ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < 0)
DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS"; DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
} }
} }
...@@ -778,35 +739,34 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) { ...@@ -778,35 +739,34 @@ void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) {
// Now set the special flags to the default values // Now set the special flags to the default values
v4l2_queryctrl range = {}; v4l2_queryctrl range = {};
range.id = V4L2_CID_AUTO_WHITE_BALANCE; range.id = V4L2_CID_AUTO_WHITE_BALANCE;
HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range)); DoIoctl(VIDIOC_QUERYCTRL, &range);
auto_white_balance.value = range.default_value; auto_white_balance.value = range.default_value;
HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance)); DoIoctl(VIDIOC_S_CTRL, &auto_white_balance);
special_camera_controls.clear(); special_camera_controls.clear();
memset(&range, 0, sizeof(struct v4l2_queryctrl)); memset(&range, 0, sizeof(range));
range.id = V4L2_CID_EXPOSURE_AUTO; range.id = V4L2_CID_EXPOSURE_AUTO;
HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range)); DoIoctl(VIDIOC_QUERYCTRL, &range);
auto_exposure.value = range.default_value; auto_exposure.value = range.default_value;
special_camera_controls.push_back(auto_exposure); special_camera_controls.push_back(auto_exposure);
memset(&range, 0, sizeof(struct v4l2_queryctrl)); memset(&range, 0, sizeof(range));
range.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY; range.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range)); DoIoctl(VIDIOC_QUERYCTRL, &range);
priority_auto_exposure.value = range.default_value; priority_auto_exposure.value = range.default_value;
special_camera_controls.push_back(priority_auto_exposure); special_camera_controls.push_back(priority_auto_exposure);
memset(&range, 0, sizeof(struct v4l2_queryctrl)); memset(&range, 0, sizeof(range));
range.id = V4L2_CID_FOCUS_AUTO; range.id = V4L2_CID_FOCUS_AUTO;
HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range)); DoIoctl(VIDIOC_QUERYCTRL, &range);
auto_focus.value = range.default_value; auto_focus.value = range.default_value;
special_camera_controls.push_back(auto_focus); special_camera_controls.push_back(auto_focus);
memset(&ext_controls, 0, sizeof(struct v4l2_ext_controls)); memset(&ext_controls, 0, sizeof(ext_controls));
ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS; ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
ext_controls.count = special_camera_controls.size(); ext_controls.count = special_camera_controls.size();
ext_controls.controls = special_camera_controls.data(); ext_controls.controls = special_camera_controls.data();
if (HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < if (DoIoctl(VIDIOC_S_EXT_CTRLS, &ext_controls) < 0)
0)
DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS"; DPLOG(INFO) << "VIDIOC_S_EXT_CTRLS";
} }
...@@ -814,8 +774,7 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) { ...@@ -814,8 +774,7 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
v4l2_buffer buffer; v4l2_buffer buffer;
FillV4L2Buffer(&buffer, index); FillV4L2Buffer(&buffer, index);
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < if (DoIoctl(VIDIOC_QUERYBUF, &buffer) < 0) {
0) {
DLOG(ERROR) << "Error querying status of a MMAP V4L2 buffer"; DLOG(ERROR) << "Error querying status of a MMAP V4L2 buffer";
return false; return false;
} }
...@@ -828,7 +787,7 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) { ...@@ -828,7 +787,7 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
buffer_tracker_pool_.push_back(buffer_tracker); buffer_tracker_pool_.push_back(buffer_tracker);
// Enqueue the buffer in the drivers incoming queue. // Enqueue the buffer in the drivers incoming queue.
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { if (DoIoctl(VIDIOC_QBUF, &buffer) < 0) {
DLOG(ERROR) << "Error enqueuing a V4L2 buffer back into the driver"; DLOG(ERROR) << "Error enqueuing a V4L2 buffer back into the driver";
return false; return false;
} }
...@@ -871,8 +830,7 @@ void V4L2CaptureDelegate::DoCapture() { ...@@ -871,8 +830,7 @@ void V4L2CaptureDelegate::DoCapture() {
v4l2_buffer buffer; v4l2_buffer buffer;
FillV4L2Buffer(&buffer, 0); FillV4L2Buffer(&buffer, 0);
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) < if (DoIoctl(VIDIOC_DQBUF, &buffer) < 0) {
0) {
SetErrorState(VideoCaptureError::kV4L2FailedToDequeueCaptureBuffer, SetErrorState(VideoCaptureError::kV4L2FailedToDequeueCaptureBuffer,
FROM_HERE, "Failed to dequeue capture buffer"); FROM_HERE, "Failed to dequeue capture buffer");
return; return;
...@@ -929,8 +887,7 @@ void V4L2CaptureDelegate::DoCapture() { ...@@ -929,8 +887,7 @@ void V4L2CaptureDelegate::DoCapture() {
std::move(cb).Run(std::move(blob)); std::move(cb).Run(std::move(blob));
} }
if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < if (DoIoctl(VIDIOC_QBUF, &buffer) < 0) {
0) {
SetErrorState(VideoCaptureError::kV4L2FailedToEnqueueCaptureBuffer, SetErrorState(VideoCaptureError::kV4L2FailedToEnqueueCaptureBuffer,
FROM_HERE, "Failed to enqueue capture buffer"); FROM_HERE, "Failed to enqueue capture buffer");
return; return;
......
...@@ -76,11 +76,24 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final { ...@@ -76,11 +76,24 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final {
class BufferTracker; class BufferTracker;
bool RunIoctl(int fd, int request, void* argp); // Running DoIoctl() on some devices, especially shortly after (re)opening the
mojom::RangePtr RetrieveUserControlRange(int device_fd, int control_id); // device file descriptor or (re)starting streaming, can fail but works after
void ResetUserAndCameraControlsToDefault(int device_fd); // retrying (https://crbug.com/670262). Returns false if the |request| ioctl
// fails too many times.
// void CloseDevice(); bool RunIoctl(int request, void* argp);
// Simple wrapper to do HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), ...)).
int DoIoctl(int request, void* argp);
// Creates a mojom::RangePtr with the (min, max, current, step) values of the
// control associated with |control_id|. Returns an empty Range otherwise.
mojom::RangePtr RetrieveUserControlRange(int control_id);
// Sets all user control to their default. Some controls are enabled by
// another flag, usually having the word "auto" in the name, see
// IsSpecialControl() in the .cc file. These flags are preset beforehand, then
// set to their defaults individually afterwards.
void ResetUserAndCameraControlsToDefault();
// VIDIOC_QUERYBUFs a buffer from V4L2, creates a BufferTracker for it and // VIDIOC_QUERYBUFs a buffer from V4L2, creates a BufferTracker for it and
// enqueues it (VIDIOC_QBUF) back into V4L2. // enqueues it (VIDIOC_QBUF) back into V4L2.
......
...@@ -205,7 +205,7 @@ void VideoCaptureDeviceFactoryLinux::GetDeviceDescriptors( ...@@ -205,7 +205,7 @@ void VideoCaptureDeviceFactoryLinux::GetDeviceDescriptors(
// capabilities at the same time are memory-to-memory and are skipped, see // capabilities at the same time are memory-to-memory and are skipped, see
// http://crbug.com/139356. // http://crbug.com/139356.
v4l2_capability cap; v4l2_capability cap;
if ((HANDLE_EINTR(v4l2_->ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) && if ((DoIoctl(fd.get(), VIDIOC_QUERYCAP, &cap) == 0) &&
(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE && (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE &&
!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) && !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) &&
HasUsableFormats(fd.get(), cap.capabilities)) { HasUsableFormats(fd.get(), cap.capabilities)) {
...@@ -250,6 +250,10 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormats( ...@@ -250,6 +250,10 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormats(
GetSupportedFormatsForV4L2BufferType(fd.get(), supported_formats); GetSupportedFormatsForV4L2BufferType(fd.get(), supported_formats);
} }
int VideoCaptureDeviceFactoryLinux::DoIoctl(int fd, int request, void* argp) {
return HANDLE_EINTR(v4l2_->ioctl(fd, request, argp));
}
bool VideoCaptureDeviceFactoryLinux::HasUsableFormats(int fd, bool VideoCaptureDeviceFactoryLinux::HasUsableFormats(int fd,
uint32_t capabilities) { uint32_t capabilities) {
if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE)) if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
...@@ -259,8 +263,7 @@ bool VideoCaptureDeviceFactoryLinux::HasUsableFormats(int fd, ...@@ -259,8 +263,7 @@ bool VideoCaptureDeviceFactoryLinux::HasUsableFormats(int fd,
VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false); VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false);
v4l2_fmtdesc fmtdesc = {}; v4l2_fmtdesc fmtdesc = {};
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (; HANDLE_EINTR(v4l2_->ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0; for (; DoIoctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
++fmtdesc.index) {
if (base::ContainsValue(usable_fourccs, fmtdesc.pixelformat)) if (base::ContainsValue(usable_fourccs, fmtdesc.pixelformat))
return true; return true;
} }
...@@ -280,8 +283,7 @@ std::vector<float> VideoCaptureDeviceFactoryLinux::GetFrameRateList( ...@@ -280,8 +283,7 @@ std::vector<float> VideoCaptureDeviceFactoryLinux::GetFrameRateList(
frame_interval.pixel_format = fourcc; frame_interval.pixel_format = fourcc;
frame_interval.width = width; frame_interval.width = width;
frame_interval.height = height; frame_interval.height = height;
for (; HANDLE_EINTR(v4l2_->ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, for (; DoIoctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval) == 0;
&frame_interval)) == 0;
++frame_interval.index) { ++frame_interval.index) {
if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) { if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
if (frame_interval.discrete.numerator != 0) { if (frame_interval.discrete.numerator != 0) {
...@@ -308,8 +310,7 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormatsForV4L2BufferType( ...@@ -308,8 +310,7 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormatsForV4L2BufferType(
VideoCaptureFormats* supported_formats) { VideoCaptureFormats* supported_formats) {
v4l2_fmtdesc v4l2_format = {}; v4l2_fmtdesc v4l2_format = {};
v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (; HANDLE_EINTR(v4l2_->ioctl(fd, VIDIOC_ENUM_FMT, &v4l2_format)) == 0; for (; DoIoctl(fd, VIDIOC_ENUM_FMT, &v4l2_format) == 0; ++v4l2_format.index) {
++v4l2_format.index) {
VideoCaptureFormat supported_format; VideoCaptureFormat supported_format;
supported_format.pixel_format = supported_format.pixel_format =
VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat( VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(
...@@ -320,8 +321,7 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormatsForV4L2BufferType( ...@@ -320,8 +321,7 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormatsForV4L2BufferType(
v4l2_frmsizeenum frame_size = {}; v4l2_frmsizeenum frame_size = {};
frame_size.pixel_format = v4l2_format.pixelformat; frame_size.pixel_format = v4l2_format.pixelformat;
for (; HANDLE_EINTR( for (; DoIoctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0;
v4l2_->ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 0;
++frame_size.index) { ++frame_size.index) {
if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
supported_format.frame_size.SetSize(frame_size.discrete.width, supported_format.frame_size.SetSize(frame_size.discrete.width,
......
...@@ -64,6 +64,9 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactoryLinux ...@@ -64,6 +64,9 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactoryLinux
VideoCaptureFormats* supported_formats) override; VideoCaptureFormats* supported_formats) override;
private: private:
// Simple wrapper to do HANDLE_EINTR(v4l2_->ioctl(fd, ...)).
int DoIoctl(int fd, int request, void* argp);
bool HasUsableFormats(int fd, uint32_t capabilities); bool HasUsableFormats(int fd, uint32_t capabilities);
std::vector<float> GetFrameRateList(int fd, std::vector<float> GetFrameRateList(int fd,
uint32_t fourcc, uint32_t fourcc,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment