Index: media/video/capture/linux/video_capture_device_linux.cc |
diff --git a/media/video/capture/linux/video_capture_device_linux.cc b/media/video/capture/linux/video_capture_device_linux.cc |
index fa3f83b3d00fab1499306d991ef48870dddb6bc7..de7f5ac2aeebe46712ab4dd02f8d875150ed53df 100644 |
--- a/media/video/capture/linux/video_capture_device_linux.cc |
+++ b/media/video/capture/linux/video_capture_device_linux.cc |
@@ -19,6 +19,7 @@ |
#include "base/bind.h" |
#include "base/files/file_enumerator.h" |
+#include "base/files/scoped_file.h" |
#include "base/posix/eintr_wrapper.h" |
#include "base/strings/stringprintf.h" |
@@ -119,19 +120,18 @@ void VideoCaptureDevice::GetDeviceNames(Names* device_names) { |
base::FileEnumerator::FileInfo info = enumerator.GetInfo(); |
std::string unique_id = path.value() + info.GetName().value(); |
- int fd; |
- if ((fd = HANDLE_EINTR(open(unique_id.c_str() , O_RDONLY))) < 0) { |
+ base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY))); |
+ if (!fd) { |
// Failed to open this device. |
continue; |
} |
- file_util::ScopedFD fd_closer(&fd); |
// Test if this is a V4L2 capture device. |
v4l2_capability cap; |
- if ((HANDLE_EINTR(ioctl(fd, VIDIOC_QUERYCAP, &cap)) == 0) && |
+ if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) && |
(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && |
!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { |
// This is a V4L2 video capture device |
- if (HasUsableFormats(fd)) { |
+ if (HasUsableFormats(fd.get())) { |
Name device_name(base::StringPrintf("%s", cap.card), unique_id); |
device_names->push_back(device_name); |
} else { |
@@ -146,19 +146,18 @@ void VideoCaptureDevice::GetDeviceSupportedFormats( |
VideoCaptureFormats* supported_formats) { |
if (device.id().empty()) |
return; |
- int fd; |
- if ((fd = HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))) < 0) { |
+ base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))); |
+ if (!fd) { |
// Failed to open this device. |
return; |
} |
- file_util::ScopedFD fd_closer(&fd); |
supported_formats->clear(); |
// Retrieve the caps one by one, first get pixel format, then sizes, then |
// frame rates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference. |
v4l2_fmtdesc pixel_format = {}; |
pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
- while (HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &pixel_format)) == 0) { |
+ while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FMT, &pixel_format)) == 0) { |
VideoCaptureFormat supported_format; |
supported_format.pixel_format = |
V4l2ColorToVideoCaptureColorFormat((int32)pixel_format.pixelformat); |
@@ -169,7 +168,8 @@ void VideoCaptureDevice::GetDeviceSupportedFormats( |
v4l2_frmsizeenum frame_size = {}; |
frame_size.pixel_format = pixel_format.pixelformat; |
- while (HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 0) { |
+ while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FRAMESIZES, &frame_size)) == |
+ 0) { |
if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { |
supported_format.frame_size.SetSize( |
frame_size.discrete.width, frame_size.discrete.height); |
@@ -184,8 +184,8 @@ void VideoCaptureDevice::GetDeviceSupportedFormats( |
frame_interval.pixel_format = pixel_format.pixelformat; |
frame_interval.width = frame_size.discrete.width; |
frame_interval.height = frame_size.discrete.height; |
- while (HANDLE_EINTR( |
- ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0) { |
+ while (HANDLE_EINTR(ioctl( |
+ fd.get(), VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0) { |
if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) { |
if (frame_interval.discrete.numerator != 0) { |
supported_format.frame_rate = |
@@ -255,13 +255,12 @@ VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) { |
// Test opening the device driver. This is to make sure it is available. |
// We will reopen it again in our worker thread when someone |
// allocates the camera. |
- int fd = HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY)); |
- if (fd < 0) { |
+ base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY))); |
+ if (!fd) { |
DVLOG(1) << "Cannot open device"; |
delete self; |
return NULL; |
} |
- close(fd); |
return self; |
} |
@@ -269,7 +268,6 @@ VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) { |
VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) |
: state_(kIdle), |
device_name_(device_name), |
- device_fd_(-1), |
v4l2_thread_("V4L2Thread"), |
buffer_pool_(NULL), |
buffer_pool_size_(0), |
@@ -324,21 +322,19 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
client_ = client.Pass(); |
// Need to open camera with O_RDWR after Linux kernel 3.3. |
- device_fd_ = HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR)); |
- if (device_fd_ < 0) { |
+ device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR))); |
+ if (!device_fd_) { |
SetErrorState("Failed to open V4L2 device driver."); |
return; |
} |
- device_fd_closer_.reset(&device_fd_); |
// Test if this is a V4L2 capture device. |
v4l2_capability cap; |
- if (!((HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QUERYCAP, &cap)) == 0) && |
+ if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) && |
(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && |
!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) { |
// This is not a V4L2 video capture device. |
- device_fd_closer_.reset(); |
- device_fd_ = -1; |
+ device_fd_.reset(); |
SetErrorState("This is not a V4L2 video capture device"); |
return; |
} |
@@ -355,7 +351,8 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
// Enumerate image formats. |
std::list<int>::iterator best = v4l2_formats.end(); |
- while (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) { |
+ while (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == |
+ 0) { |
best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat); |
fmtdesc.index++; |
} |
@@ -374,7 +371,7 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
video_fmt.fmt.pix.height = height; |
video_fmt.fmt.pix.pixelformat = *best; |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_S_FMT, &video_fmt)) < 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt)) < 0) { |
SetErrorState("Failed to set camera format"); |
return; |
} |
@@ -384,14 +381,15 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
memset(&streamparm, 0, sizeof(v4l2_streamparm)); |
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
// The following line checks that the driver knows about framerate get/set. |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_G_PARM, &streamparm)) >= 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) { |
// Now check if the device is able to accept a capture framerate set. |
if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) { |
streamparm.parm.capture.timeperframe.numerator = 1; |
streamparm.parm.capture.timeperframe.denominator = |
(frame_rate) ? frame_rate : kTypicalFramerate; |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_S_PARM, &streamparm)) < 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < |
+ 0) { |
SetErrorState("Failed to set camera framerate"); |
return; |
} |
@@ -419,7 +417,7 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
// Start UVC camera. |
v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_STREAMON, &type)) == -1) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &type)) == -1) { |
SetErrorState("VIDIOC_STREAMON failed"); |
return; |
} |
@@ -436,7 +434,7 @@ void VideoCaptureDeviceLinux::OnStopAndDeAllocate() { |
DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); |
v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_STREAMOFF, &type)) < 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &type)) < 0) { |
SetErrorState("VIDIOC_STREAMOFF failed"); |
return; |
} |
@@ -447,8 +445,7 @@ void VideoCaptureDeviceLinux::OnStopAndDeAllocate() { |
// We need to close and open the device if we want to change the settings |
// Otherwise VIDIOC_S_FMT will return error |
// Sad but true. |
- device_fd_closer_.reset(); |
- device_fd_ = -1; |
+ device_fd_.reset(); |
state_ = kIdle; |
client_.reset(); |
} |
@@ -462,7 +459,7 @@ void VideoCaptureDeviceLinux::OnCaptureTask() { |
fd_set r_set; |
FD_ZERO(&r_set); |
- FD_SET(device_fd_, &r_set); |
+ FD_SET(device_fd_.get(), &r_set); |
timeval timeout; |
timeout.tv_sec = 0; |
@@ -471,7 +468,7 @@ void VideoCaptureDeviceLinux::OnCaptureTask() { |
// First argument to select is the highest numbered file descriptor +1. |
// Refer to http://linux.die.net/man/2/select for more information. |
int result = |
- HANDLE_EINTR(select(device_fd_ + 1, &r_set, NULL, NULL, &timeout)); |
+ HANDLE_EINTR(select(device_fd_.get() + 1, &r_set, NULL, NULL, &timeout)); |
// Check if select have failed. |
if (result < 0) { |
// EINTR is a signal. This is not really an error. |
@@ -500,13 +497,13 @@ void VideoCaptureDeviceLinux::OnCaptureTask() { |
} |
// Check if the driver have filled a buffer. |
- if (FD_ISSET(device_fd_, &r_set)) { |
+ if (FD_ISSET(device_fd_.get(), &r_set)) { |
v4l2_buffer buffer; |
memset(&buffer, 0, sizeof(buffer)); |
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
buffer.memory = V4L2_MEMORY_MMAP; |
// Dequeue a buffer. |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_DQBUF, &buffer)) == 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { |
client_->OnIncomingCapturedData( |
static_cast<uint8*>(buffer_pool_[buffer.index].start), |
buffer.bytesused, |
@@ -515,7 +512,7 @@ void VideoCaptureDeviceLinux::OnCaptureTask() { |
base::TimeTicks::Now()); |
// Enqueue the buffer again. |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QBUF, &buffer)) == -1) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { |
SetErrorState(base::StringPrintf( |
"Failed to enqueue capture buffer errno %d", errno)); |
} |
@@ -540,7 +537,7 @@ bool VideoCaptureDeviceLinux::AllocateVideoBuffers() { |
r_buffer.memory = V4L2_MEMORY_MMAP; |
r_buffer.count = kMaxVideoBuffers; |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer)) < 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) { |
return false; |
} |
@@ -559,20 +556,20 @@ bool VideoCaptureDeviceLinux::AllocateVideoBuffers() { |
buffer.memory = V4L2_MEMORY_MMAP; |
buffer.index = i; |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QUERYBUF, &buffer)) < 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) { |
return false; |
} |
// Some devices require mmap() to be called with both READ and WRITE. |
// See crbug.com/178582. |
buffer_pool_[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, |
- MAP_SHARED, device_fd_, buffer.m.offset); |
+ MAP_SHARED, device_fd_.get(), buffer.m.offset); |
if (buffer_pool_[i].start == MAP_FAILED) { |
return false; |
} |
buffer_pool_[i].length = buffer.length; |
// Enqueue the buffer in the drivers incoming queue. |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_QBUF, &buffer)) < 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { |
return false; |
} |
} |
@@ -593,7 +590,7 @@ void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() { |
r_buffer.memory = V4L2_MEMORY_MMAP; |
r_buffer.count = 0; |
- if (HANDLE_EINTR(ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer)) < 0) { |
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) { |
SetErrorState("Failed to reset buf."); |
} |