linux_aura: Disable the plugin install infobar.
[chromium-blink-merge.git] / media / video / capture / linux / video_capture_device_factory_linux.cc
blob5627dc0f8eea3a2bb4cf5b54feb4afe4217fb2a6
1 // Copyright 2014 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.
5 #include "media/video/capture/linux/video_capture_device_factory_linux.h"
7 #include <errno.h>
8 #include <fcntl.h>
9 #if defined(OS_OPENBSD)
10 #include <sys/videoio.h>
11 #else
12 #include <linux/videodev2.h>
13 #endif
14 #include <sys/ioctl.h>
16 #include "base/files/file_enumerator.h"
17 #include "base/files/scoped_file.h"
18 #include "base/posix/eintr_wrapper.h"
19 #include "base/strings/stringprintf.h"
20 #if defined(OS_CHROMEOS)
21 #include "media/video/capture/linux/video_capture_device_chromeos.h"
22 #endif
23 #include "media/video/capture/linux/video_capture_device_linux.h"
25 namespace media {
27 static bool HasUsableFormats(int fd) {
28 v4l2_fmtdesc fmtdesc;
29 std::list<int> usable_fourccs;
31 media::VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false,
32 &usable_fourccs);
34 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
35 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
37 while (HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) {
38 if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
39 fmtdesc.pixelformat) != usable_fourccs.end())
40 return true;
42 fmtdesc.index++;
44 return false;
47 scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryLinux::Create(
48 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
49 const VideoCaptureDevice::Name& device_name) {
50 DCHECK(thread_checker_.CalledOnValidThread());
51 #if defined(OS_CHROMEOS)
52 VideoCaptureDeviceChromeOS* self =
53 new VideoCaptureDeviceChromeOS(ui_task_runner, device_name);
54 #else
55 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name);
56 #endif
57 if (!self)
58 return scoped_ptr<VideoCaptureDevice>();
59 // Test opening the device driver. This is to make sure it is available.
60 // We will reopen it again in our worker thread when someone
61 // allocates the camera.
62 base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY)));
63 if (!fd.is_valid()) {
64 DVLOG(1) << "Cannot open device";
65 delete self;
66 return scoped_ptr<VideoCaptureDevice>();
69 return scoped_ptr<VideoCaptureDevice>(self);
72 void VideoCaptureDeviceFactoryLinux::GetDeviceNames(
73 VideoCaptureDevice::Names* const device_names) {
74 DCHECK(thread_checker_.CalledOnValidThread());
75 DCHECK(device_names->empty());
76 base::FilePath path("/dev/");
77 base::FileEnumerator enumerator(
78 path, false, base::FileEnumerator::FILES, "video*");
80 while (!enumerator.Next().empty()) {
81 base::FileEnumerator::FileInfo info = enumerator.GetInfo();
83 std::string unique_id = path.value() + info.GetName().value();
84 base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY)));
85 if (!fd.is_valid()) {
86 // Failed to open this device.
87 continue;
89 // Test if this is a V4L2 capture device.
90 v4l2_capability cap;
91 if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
92 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
93 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
94 // This is a V4L2 video capture device
95 if (HasUsableFormats(fd.get())) {
96 VideoCaptureDevice::Name device_name(base::StringPrintf("%s", cap.card),
97 unique_id);
98 device_names->push_back(device_name);
99 } else {
100 DVLOG(1) << "No usable formats reported by " << info.GetName().value();
106 void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats(
107 const VideoCaptureDevice::Name& device,
108 VideoCaptureFormats* supported_formats) {
109 DCHECK(thread_checker_.CalledOnValidThread());
110 if (device.id().empty())
111 return;
112 base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY)));
113 if (!fd.is_valid()) {
114 // Failed to open this device.
115 return;
117 supported_formats->clear();
119 // Retrieve the caps one by one, first get pixel format, then sizes, then
120 // frame rates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference.
121 v4l2_fmtdesc pixel_format = {};
122 pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
123 while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FMT, &pixel_format)) == 0) {
124 VideoCaptureFormat supported_format;
125 supported_format.pixel_format =
126 VideoCaptureDeviceLinux::V4l2ColorToVideoCaptureColorFormat(
127 (int32)pixel_format.pixelformat);
128 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) {
129 ++pixel_format.index;
130 continue;
133 v4l2_frmsizeenum frame_size = {};
134 frame_size.pixel_format = pixel_format.pixelformat;
135 while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FRAMESIZES, &frame_size)) ==
136 0) {
137 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
138 supported_format.frame_size.SetSize(
139 frame_size.discrete.width, frame_size.discrete.height);
140 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
141 // TODO(mcasas): see http://crbug.com/249953, support these devices.
142 NOTIMPLEMENTED();
143 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
144 // TODO(mcasas): see http://crbug.com/249953, support these devices.
145 NOTIMPLEMENTED();
147 v4l2_frmivalenum frame_interval = {};
148 frame_interval.pixel_format = pixel_format.pixelformat;
149 frame_interval.width = frame_size.discrete.width;
150 frame_interval.height = frame_size.discrete.height;
151 while (HANDLE_EINTR(ioctl(
152 fd.get(), VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0) {
153 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
154 if (frame_interval.discrete.numerator != 0) {
155 supported_format.frame_rate =
156 static_cast<float>(frame_interval.discrete.denominator) /
157 static_cast<float>(frame_interval.discrete.numerator);
158 } else {
159 supported_format.frame_rate = 0;
161 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
162 // TODO(mcasas): see http://crbug.com/249953, support these devices.
163 NOTIMPLEMENTED();
164 break;
165 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
166 // TODO(mcasas): see http://crbug.com/249953, support these devices.
167 NOTIMPLEMENTED();
168 break;
170 supported_formats->push_back(supported_format);
171 ++frame_interval.index;
173 ++frame_size.index;
175 ++pixel_format.index;
177 return;
180 } // namespace media