Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(424)

Side by Side Diff: media/capture/video/linux/video_capture_device_factory_linux.cc

Issue 2143903003: [WIP] Move media/capture to device/capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "media/capture/video/linux/video_capture_device_factory_linux.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stdint.h>
10 #include <sys/ioctl.h>
11
12 #include "base/files/file_enumerator.h"
13 #include "base/files/scoped_file.h"
14 #include "base/posix/eintr_wrapper.h"
15 #include "build/build_config.h"
16
17 #if defined(OS_OPENBSD)
18 #include <sys/videoio.h>
19 #else
20 #include <linux/videodev2.h>
21 #endif
22
23 #if defined(OS_CHROMEOS)
24 #include "media/capture/video/linux/video_capture_device_chromeos.h"
25 #endif
26 #include "media/capture/video/linux/video_capture_device_linux.h"
27
28 namespace media {
29
30 static bool HasUsableFormats(int fd, uint32_t capabilities) {
31 if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
32 return false;
33
34 const std::list<uint32_t>& usable_fourccs =
35 VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false);
36 v4l2_fmtdesc fmtdesc = {};
37 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
38 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0;
39 ++fmtdesc.index) {
40 if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
41 fmtdesc.pixelformat) != usable_fourccs.end()) {
42 return true;
43 }
44 }
45
46 DLOG(ERROR) << "No usable formats found";
47 return false;
48 }
49
50 static std::list<float> GetFrameRateList(int fd,
51 uint32_t fourcc,
52 uint32_t width,
53 uint32_t height) {
54 std::list<float> frame_rates;
55
56 v4l2_frmivalenum frame_interval = {};
57 frame_interval.pixel_format = fourcc;
58 frame_interval.width = width;
59 frame_interval.height = height;
60 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) ==
61 0;
62 ++frame_interval.index) {
63 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
64 if (frame_interval.discrete.numerator != 0) {
65 frame_rates.push_back(
66 frame_interval.discrete.denominator /
67 static_cast<float>(frame_interval.discrete.numerator));
68 }
69 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
70 frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
71 // TODO(mcasas): see http://crbug.com/249953, support these devices.
72 NOTIMPLEMENTED();
73 break;
74 }
75 }
76 // Some devices, e.g. Kinect, do not enumerate any frame rates, see
77 // http://crbug.com/412284. Set their frame_rate to zero.
78 if (frame_rates.empty())
79 frame_rates.push_back(0);
80 return frame_rates;
81 }
82
83 static void GetSupportedFormatsForV4L2BufferType(
84 int fd,
85 media::VideoCaptureFormats* supported_formats) {
86 v4l2_fmtdesc v4l2_format = {};
87 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
88 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &v4l2_format)) == 0;
89 ++v4l2_format.index) {
90 VideoCaptureFormat supported_format;
91 supported_format.pixel_format =
92 VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(
93 v4l2_format.pixelformat);
94
95 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN)
96 continue;
97
98 v4l2_frmsizeenum frame_size = {};
99 frame_size.pixel_format = v4l2_format.pixelformat;
100 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 0;
101 ++frame_size.index) {
102 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
103 supported_format.frame_size.SetSize(frame_size.discrete.width,
104 frame_size.discrete.height);
105 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
106 frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
107 // TODO(mcasas): see http://crbug.com/249953, support these devices.
108 NOTIMPLEMENTED();
109 }
110
111 const std::list<float> frame_rates = GetFrameRateList(
112 fd, v4l2_format.pixelformat, frame_size.discrete.width,
113 frame_size.discrete.height);
114 for (const auto& frame_rate : frame_rates) {
115 supported_format.frame_rate = frame_rate;
116 supported_formats->push_back(supported_format);
117 DVLOG(1) << VideoCaptureFormat::ToString(supported_format);
118 }
119 }
120 }
121 }
122
123 VideoCaptureDeviceFactoryLinux::VideoCaptureDeviceFactoryLinux(
124 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
125 : ui_task_runner_(ui_task_runner) {
126 }
127
128 VideoCaptureDeviceFactoryLinux::~VideoCaptureDeviceFactoryLinux() {
129 }
130
131 std::unique_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryLinux::Create(
132 const VideoCaptureDevice::Name& device_name) {
133 DCHECK(thread_checker_.CalledOnValidThread());
134 #if defined(OS_CHROMEOS)
135 VideoCaptureDeviceChromeOS* self =
136 new VideoCaptureDeviceChromeOS(ui_task_runner_, device_name);
137 #else
138 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name);
139 #endif
140 if (!self)
141 return std::unique_ptr<VideoCaptureDevice>();
142 // Test opening the device driver. This is to make sure it is available.
143 // We will reopen it again in our worker thread when someone
144 // allocates the camera.
145 base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY)));
146 if (!fd.is_valid()) {
147 DLOG(ERROR) << "Cannot open device";
148 delete self;
149 return std::unique_ptr<VideoCaptureDevice>();
150 }
151
152 return std::unique_ptr<VideoCaptureDevice>(self);
153 }
154
155 void VideoCaptureDeviceFactoryLinux::GetDeviceNames(
156 VideoCaptureDevice::Names* const device_names) {
157 DCHECK(thread_checker_.CalledOnValidThread());
158 DCHECK(device_names->empty());
159 const base::FilePath path("/dev/");
160 base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
161 "video*");
162
163 while (!enumerator.Next().empty()) {
164 const base::FileEnumerator::FileInfo info = enumerator.GetInfo();
165 const std::string unique_id = path.value() + info.GetName().value();
166 const base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY)));
167 if (!fd.is_valid()) {
168 DLOG(ERROR) << "Couldn't open " << info.GetName().value();
169 continue;
170 }
171 // Test if this is a V4L2 capture device and if it has at least one
172 // supported capture format. Devices that have capture and output
173 // capabilities at the same time are memory-to-memory and are skipped, see
174 // http://crbug.com/139356.
175 v4l2_capability cap;
176 if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
177 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE &&
178 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) &&
179 HasUsableFormats(fd.get(), cap.capabilities)) {
180 device_names->push_back(VideoCaptureDevice::Name(
181 reinterpret_cast<char*>(cap.card), unique_id,
182 VideoCaptureDevice::Name::V4L2_SINGLE_PLANE));
183 }
184 }
185 }
186
187 void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats(
188 const VideoCaptureDevice::Name& device,
189 VideoCaptureFormats* supported_formats) {
190 DCHECK(thread_checker_.CalledOnValidThread());
191 if (device.id().empty())
192 return;
193 base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY)));
194 if (!fd.is_valid()) // Failed to open this device.
195 return;
196 supported_formats->clear();
197
198 DCHECK_NE(device.capture_api_type(),
199 VideoCaptureDevice::Name::API_TYPE_UNKNOWN);
200 GetSupportedFormatsForV4L2BufferType(fd.get(), supported_formats);
201 }
202
203 // static
204 VideoCaptureDeviceFactory*
205 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
206 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
207 return new VideoCaptureDeviceFactoryLinux(ui_task_runner);
208 }
209
210 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/video/linux/video_capture_device_factory_linux.h ('k') | media/capture/video/linux/video_capture_device_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698