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

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

Issue 804473007: Linux Video Capture: small cleanup (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/video/capture/linux/video_capture_device_factory_linux.h" 5 #include "media/video/capture/linux/video_capture_device_factory_linux.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #if defined(OS_OPENBSD) 9 #if defined(OS_OPENBSD)
10 #include <sys/videoio.h> 10 #include <sys/videoio.h>
11 #else 11 #else
12 #include <linux/videodev2.h> 12 #include <linux/videodev2.h>
13 #endif 13 #endif
14 #include <sys/ioctl.h> 14 #include <sys/ioctl.h>
15 15
16 #include "base/files/file_enumerator.h" 16 #include "base/files/file_enumerator.h"
17 #include "base/files/scoped_file.h" 17 #include "base/files/scoped_file.h"
18 #include "base/posix/eintr_wrapper.h" 18 #include "base/posix/eintr_wrapper.h"
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #if defined(OS_CHROMEOS) 20 #if defined(OS_CHROMEOS)
21 #include "media/video/capture/linux/video_capture_device_chromeos.h" 21 #include "media/video/capture/linux/video_capture_device_chromeos.h"
22 #endif 22 #endif
23 #include "media/video/capture/linux/video_capture_device_linux.h" 23 #include "media/video/capture/linux/video_capture_device_linux.h"
24 24
25 namespace media { 25 namespace media {
26 26
27 static bool HasUsableFormats(int fd) { 27 static int Ioctl(const base::ScopedFD& device_fd, int request, void* arg) {
28 v4l2_fmtdesc fmtdesc; 28 return VideoCaptureDeviceLinux::Ioctl(device_fd, request, arg);
29 std::list<int> usable_fourccs; 29 }
30 30
31 media::VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false, 31 static bool HasUsableFormats(const base::ScopedFD& device_fd) {
32 &usable_fourccs); 32 const std::list<int>& usable_fourccs =
33 VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false);
33 34
34 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc)); 35 v4l2_fmtdesc fmtdesc = {};
35 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 36 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
36 37 for (; Ioctl(device_fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
37 while (HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) {
38 if (std::find(usable_fourccs.begin(), usable_fourccs.end(), 38 if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
39 fmtdesc.pixelformat) != usable_fourccs.end()) 39 fmtdesc.pixelformat) != usable_fourccs.end())
40 return true; 40 return true;
41
42 fmtdesc.index++;
43 } 41 }
44 return false; 42 return false;
45 } 43 }
46 44
47 VideoCaptureDeviceFactoryLinux::VideoCaptureDeviceFactoryLinux( 45 VideoCaptureDeviceFactoryLinux::VideoCaptureDeviceFactoryLinux(
48 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) 46 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
49 : ui_task_runner_(ui_task_runner) { 47 : ui_task_runner_(ui_task_runner) {
50 } 48 }
51 49
52 VideoCaptureDeviceFactoryLinux::~VideoCaptureDeviceFactoryLinux() { 50 VideoCaptureDeviceFactoryLinux::~VideoCaptureDeviceFactoryLinux() {
(...skipping 20 matching lines...) Expand all
73 return scoped_ptr<VideoCaptureDevice>(); 71 return scoped_ptr<VideoCaptureDevice>();
74 } 72 }
75 73
76 return scoped_ptr<VideoCaptureDevice>(self); 74 return scoped_ptr<VideoCaptureDevice>(self);
77 } 75 }
78 76
79 void VideoCaptureDeviceFactoryLinux::GetDeviceNames( 77 void VideoCaptureDeviceFactoryLinux::GetDeviceNames(
80 VideoCaptureDevice::Names* const device_names) { 78 VideoCaptureDevice::Names* const device_names) {
81 DCHECK(thread_checker_.CalledOnValidThread()); 79 DCHECK(thread_checker_.CalledOnValidThread());
82 DCHECK(device_names->empty()); 80 DCHECK(device_names->empty());
83 base::FilePath path("/dev/"); 81 const base::FilePath path("/dev/");
84 base::FileEnumerator enumerator( 82 base::FileEnumerator enumerator(
85 path, false, base::FileEnumerator::FILES, "video*"); 83 path, false, base::FileEnumerator::FILES, "video*");
86 84
87 while (!enumerator.Next().empty()) { 85 while (!enumerator.Next().empty()) {
88 base::FileEnumerator::FileInfo info = enumerator.GetInfo(); 86 const base::FileEnumerator::FileInfo info = enumerator.GetInfo();
89 87 const std::string unique_id = path.value() + info.GetName().value();
90 std::string unique_id = path.value() + info.GetName().value(); 88 const base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY)));
91 base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY)));
92 if (!fd.is_valid()) { 89 if (!fd.is_valid()) {
93 // Failed to open this device. 90 DLOG(ERROR) << "Couldn't open " << info.GetName().value();
94 continue; 91 continue;
95 } 92 }
96 // Test if this is a V4L2 capture device. 93 // Test if this is a V4L2 capture device and if it has at least one
94 // supported capture format. Single plane capture devices should not be
95 // output devices, see http://crbug.com/139356.
perkj_chrome 2014/12/16 10:34:43 ? Can you expand on this?
mcasas 2014/12/16 18:08:17 Done.
97 v4l2_capability cap; 96 v4l2_capability cap;
98 if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) && 97 if ((Ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) &&
99 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && 98 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE &&
100 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { 99 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) &&
perkj_chrome 2014/12/16 10:34:43 the indentation was corret from the beginning.
mcasas 2014/12/16 18:08:17 Done.
101 // This is a V4L2 video capture device 100 HasUsableFormats(fd)) {
102 if (HasUsableFormats(fd.get())) { 101 device_names->push_front(VideoCaptureDevice::Name(
103 VideoCaptureDevice::Name device_name(base::StringPrintf("%s", cap.card), 102 base::StringPrintf("%s", cap.card), unique_id));
104 unique_id);
105 device_names->push_back(device_name);
106 } else {
107 DVLOG(1) << "No usable formats reported by " << info.GetName().value();
108 }
109 } 103 }
110 } 104 }
111 } 105 }
112 106
113 void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats( 107 void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats(
114 const VideoCaptureDevice::Name& device, 108 const VideoCaptureDevice::Name& device,
115 VideoCaptureFormats* supported_formats) { 109 VideoCaptureFormats* supported_formats) {
116 DCHECK(thread_checker_.CalledOnValidThread()); 110 DCHECK(thread_checker_.CalledOnValidThread());
117 if (device.id().empty()) 111 if (device.id().empty())
118 return; 112 return;
119 base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))); 113 base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY)));
120 if (!fd.is_valid()) { 114 if (!fd.is_valid()) // Failed to open this device.
121 // Failed to open this device.
122 return; 115 return;
123 }
124 supported_formats->clear(); 116 supported_formats->clear();
125 117
126 // Retrieve the caps one by one, first get pixel format, then sizes, then 118 // Retrieve the caps one by one, first get pixel format, then sizes, then
127 // frame rates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference. 119 // frame rates.
128 v4l2_fmtdesc pixel_format = {}; 120 v4l2_fmtdesc pixel_format = {};
129 pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 121 pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
130 while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FMT, &pixel_format)) == 0) { 122 for (; Ioctl(fd, VIDIOC_ENUM_FMT, &pixel_format) == 0; ++pixel_format.index) {
131 VideoCaptureFormat supported_format; 123 VideoCaptureFormat supported_format;
132 supported_format.pixel_format = 124 supported_format.pixel_format =
133 VideoCaptureDeviceLinux::V4l2ColorToVideoCaptureColorFormat( 125 VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(
134 (int32)pixel_format.pixelformat); 126 pixel_format.pixelformat);
135 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) { 127 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN)
136 ++pixel_format.index;
137 continue; 128 continue;
138 }
139 129
140 v4l2_frmsizeenum frame_size = {}; 130 v4l2_frmsizeenum frame_size = {};
141 frame_size.pixel_format = pixel_format.pixelformat; 131 frame_size.pixel_format = pixel_format.pixelformat;
142 while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 132 for (; Ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0;
143 0) { 133 ++frame_size.index) {
144 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { 134 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
145 supported_format.frame_size.SetSize( 135 supported_format.frame_size.SetSize(
146 frame_size.discrete.width, frame_size.discrete.height); 136 frame_size.discrete.width, frame_size.discrete.height);
147 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { 137 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
148 // TODO(mcasas): see http://crbug.com/249953, support these devices. 138 frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
149 NOTIMPLEMENTED();
150 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
151 // TODO(mcasas): see http://crbug.com/249953, support these devices. 139 // TODO(mcasas): see http://crbug.com/249953, support these devices.
152 NOTIMPLEMENTED(); 140 NOTIMPLEMENTED();
153 } 141 }
142
154 v4l2_frmivalenum frame_interval = {}; 143 v4l2_frmivalenum frame_interval = {};
155 frame_interval.pixel_format = pixel_format.pixelformat; 144 frame_interval.pixel_format = pixel_format.pixelformat;
156 frame_interval.width = frame_size.discrete.width; 145 frame_interval.width = frame_size.discrete.width;
157 frame_interval.height = frame_size.discrete.height; 146 frame_interval.height = frame_size.discrete.height;
158 std::list<float> frame_rates; 147 std::list<float> frame_rates;
159 while (HANDLE_EINTR(ioctl( 148 for (; Ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval) == 0;
160 fd.get(), VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0) { 149 ++frame_interval.index) {
perkj_chrome 2014/12/16 10:34:43 nit indentation.
mcasas 2014/12/16 18:08:17 Done.
161 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) { 150 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
162 if (frame_interval.discrete.numerator != 0) { 151 if (frame_interval.discrete.numerator != 0) {
163 frame_rates.push_back( 152 frame_rates.push_back(frame_interval.discrete.denominator /
164 static_cast<float>(frame_interval.discrete.denominator) /
165 static_cast<float>(frame_interval.discrete.numerator)); 153 static_cast<float>(frame_interval.discrete.numerator));
166 } 154 }
167 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { 155 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
168 // TODO(mcasas): see http://crbug.com/249953, support these devices. 156 frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
169 NOTIMPLEMENTED();
170 break;
171 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
172 // TODO(mcasas): see http://crbug.com/249953, support these devices. 157 // TODO(mcasas): see http://crbug.com/249953, support these devices.
173 NOTIMPLEMENTED(); 158 NOTIMPLEMENTED();
174 break; 159 break;
175 } 160 }
176 ++frame_interval.index;
177 } 161 }
162 // Some devices, e.g. Kinect, do not enumerate any frame rates, see
163 // http://crbug.com/412284. Set their frame_rate to zero.
164 if (frame_rates.empty())
165 frame_rates.push_back(0.0f);
178 166
179 // Some devices, e.g. Kinect, do not enumerate any frame rates. For these 167 for (const auto& it : frame_rates) {
180 // devices, we do not want to lose all enumeration (pixel format and 168 supported_format.frame_rate = it;
181 // resolution), so we return a frame rate of zero instead.
182 if (frame_rates.empty())
183 frame_rates.push_back(0);
184
185 for (std::list<float>::iterator it = frame_rates.begin();
186 it != frame_rates.end(); ++it) {
187 supported_format.frame_rate = *it;
188 supported_formats->push_back(supported_format); 169 supported_formats->push_back(supported_format);
189 DVLOG(1) << device.name() << " " << supported_format.ToString(); 170 DVLOG(1) << device.name() << " " << supported_format.ToString();
190 } 171 }
191 ++frame_size.index;
192 } 172 }
193 ++pixel_format.index;
194 } 173 }
195 return; 174 return;
196 } 175 }
197 176
198 // static 177 // static
199 VideoCaptureDeviceFactory* 178 VideoCaptureDeviceFactory*
200 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( 179 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
201 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { 180 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
202 return new VideoCaptureDeviceFactoryLinux(ui_task_runner); 181 return new VideoCaptureDeviceFactoryLinux(ui_task_runner);
203 } 182 }
204 183
205 } // namespace media 184 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698