OLD | NEW |
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/capture/video/linux/video_capture_device_factory_linux.h" | 5 #include "media/capture/video/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 #include <stdint.h> | 9 #include <stdint.h> |
10 #include <sys/ioctl.h> | 10 #include <sys/ioctl.h> |
(...skipping 10 matching lines...) Expand all Loading... |
21 #endif | 21 #endif |
22 | 22 |
23 #if defined(OS_CHROMEOS) | 23 #if defined(OS_CHROMEOS) |
24 #include "media/capture/video/linux/video_capture_device_chromeos.h" | 24 #include "media/capture/video/linux/video_capture_device_chromeos.h" |
25 #endif | 25 #endif |
26 #include "media/capture/video/linux/video_capture_device_linux.h" | 26 #include "media/capture/video/linux/video_capture_device_linux.h" |
27 | 27 |
28 namespace media { | 28 namespace media { |
29 | 29 |
30 static bool HasUsableFormats(int fd, uint32_t capabilities) { | 30 static bool HasUsableFormats(int fd, uint32_t capabilities) { |
| 31 if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE)) |
| 32 return false; |
| 33 |
31 const std::list<uint32_t>& usable_fourccs = | 34 const std::list<uint32_t>& usable_fourccs = |
32 VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false); | 35 VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false); |
33 | 36 v4l2_fmtdesc fmtdesc = {}; |
34 static const struct { | 37 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
35 int capability; | 38 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0; |
36 v4l2_buf_type buf_type; | 39 ++fmtdesc.index) { |
37 } kCapabilityAndBufferTypes[] = { | 40 if (std::find(usable_fourccs.begin(), usable_fourccs.end(), |
38 {V4L2_CAP_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_CAPTURE}, | 41 fmtdesc.pixelformat) != usable_fourccs.end()) { |
39 {V4L2_CAP_VIDEO_CAPTURE_MPLANE, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE}}; | 42 return true; |
40 | |
41 for (const auto& capability_and_buffer_type : kCapabilityAndBufferTypes) { | |
42 v4l2_fmtdesc fmtdesc = {}; | |
43 if (capabilities & capability_and_buffer_type.capability) { | |
44 fmtdesc.type = capability_and_buffer_type.buf_type; | |
45 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0; | |
46 ++fmtdesc.index) { | |
47 if (std::find(usable_fourccs.begin(), usable_fourccs.end(), | |
48 fmtdesc.pixelformat) != usable_fourccs.end()) | |
49 return true; | |
50 } | |
51 } | 43 } |
52 } | 44 } |
| 45 |
53 DLOG(ERROR) << "No usable formats found"; | 46 DLOG(ERROR) << "No usable formats found"; |
54 return false; | 47 return false; |
55 } | 48 } |
56 | 49 |
57 static std::list<float> GetFrameRateList(int fd, | 50 static std::list<float> GetFrameRateList(int fd, |
58 uint32_t fourcc, | 51 uint32_t fourcc, |
59 uint32_t width, | 52 uint32_t width, |
60 uint32_t height) { | 53 uint32_t height) { |
61 std::list<float> frame_rates; | 54 std::list<float> frame_rates; |
62 | 55 |
(...skipping 19 matching lines...) Expand all Loading... |
82 } | 75 } |
83 // Some devices, e.g. Kinect, do not enumerate any frame rates, see | 76 // Some devices, e.g. Kinect, do not enumerate any frame rates, see |
84 // http://crbug.com/412284. Set their frame_rate to zero. | 77 // http://crbug.com/412284. Set their frame_rate to zero. |
85 if (frame_rates.empty()) | 78 if (frame_rates.empty()) |
86 frame_rates.push_back(0); | 79 frame_rates.push_back(0); |
87 return frame_rates; | 80 return frame_rates; |
88 } | 81 } |
89 | 82 |
90 static void GetSupportedFormatsForV4L2BufferType( | 83 static void GetSupportedFormatsForV4L2BufferType( |
91 int fd, | 84 int fd, |
92 v4l2_buf_type buf_type, | |
93 media::VideoCaptureFormats* supported_formats) { | 85 media::VideoCaptureFormats* supported_formats) { |
94 v4l2_fmtdesc v4l2_format = {}; | 86 v4l2_fmtdesc v4l2_format = {}; |
95 v4l2_format.type = buf_type; | 87 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
96 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &v4l2_format)) == 0; | 88 for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &v4l2_format)) == 0; |
97 ++v4l2_format.index) { | 89 ++v4l2_format.index) { |
98 VideoCaptureFormat supported_format; | 90 VideoCaptureFormat supported_format; |
99 supported_format.pixel_format = | 91 supported_format.pixel_format = |
100 VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat( | 92 VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat( |
101 v4l2_format.pixelformat); | 93 v4l2_format.pixelformat); |
102 | 94 |
103 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) | 95 if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) |
104 continue; | 96 continue; |
105 | 97 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 if (!fd.is_valid()) { | 167 if (!fd.is_valid()) { |
176 DLOG(ERROR) << "Couldn't open " << info.GetName().value(); | 168 DLOG(ERROR) << "Couldn't open " << info.GetName().value(); |
177 continue; | 169 continue; |
178 } | 170 } |
179 // Test if this is a V4L2 capture device and if it has at least one | 171 // Test if this is a V4L2 capture device and if it has at least one |
180 // supported capture format. Devices that have capture and output | 172 // supported capture format. Devices that have capture and output |
181 // capabilities at the same time are memory-to-memory and are skipped, see | 173 // capabilities at the same time are memory-to-memory and are skipped, see |
182 // http://crbug.com/139356. | 174 // http://crbug.com/139356. |
183 v4l2_capability cap; | 175 v4l2_capability cap; |
184 if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) && | 176 if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) && |
185 ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE || | 177 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE && |
186 cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) && | 178 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) && |
187 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) && | |
188 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) && | |
189 HasUsableFormats(fd.get(), cap.capabilities)) { | 179 HasUsableFormats(fd.get(), cap.capabilities)) { |
190 device_names->push_back(VideoCaptureDevice::Name( | 180 device_names->push_back(VideoCaptureDevice::Name( |
191 reinterpret_cast<char*>(cap.card), unique_id, | 181 reinterpret_cast<char*>(cap.card), unique_id, |
192 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) | 182 VideoCaptureDevice::Name::V4L2_SINGLE_PLANE)); |
193 ? VideoCaptureDevice::Name::V4L2_MULTI_PLANE | |
194 : VideoCaptureDevice::Name::V4L2_SINGLE_PLANE)); | |
195 } | 183 } |
196 } | 184 } |
197 } | 185 } |
198 | 186 |
199 void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats( | 187 void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats( |
200 const VideoCaptureDevice::Name& device, | 188 const VideoCaptureDevice::Name& device, |
201 VideoCaptureFormats* supported_formats) { | 189 VideoCaptureFormats* supported_formats) { |
202 DCHECK(thread_checker_.CalledOnValidThread()); | 190 DCHECK(thread_checker_.CalledOnValidThread()); |
203 if (device.id().empty()) | 191 if (device.id().empty()) |
204 return; | 192 return; |
205 base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))); | 193 base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))); |
206 if (!fd.is_valid()) // Failed to open this device. | 194 if (!fd.is_valid()) // Failed to open this device. |
207 return; | 195 return; |
208 supported_formats->clear(); | 196 supported_formats->clear(); |
209 | 197 |
210 DCHECK_NE(device.capture_api_type(), | 198 DCHECK_NE(device.capture_api_type(), |
211 VideoCaptureDevice::Name::API_TYPE_UNKNOWN); | 199 VideoCaptureDevice::Name::API_TYPE_UNKNOWN); |
212 const v4l2_buf_type buf_type = | 200 GetSupportedFormatsForV4L2BufferType(fd.get(), supported_formats); |
213 (device.capture_api_type() == VideoCaptureDevice::Name::V4L2_MULTI_PLANE) | |
214 ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE | |
215 : V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
216 GetSupportedFormatsForV4L2BufferType(fd.get(), buf_type, supported_formats); | |
217 | |
218 return; | |
219 } | 201 } |
220 | 202 |
221 // static | 203 // static |
222 VideoCaptureDeviceFactory* | 204 VideoCaptureDeviceFactory* |
223 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( | 205 VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( |
224 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 206 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
225 return new VideoCaptureDeviceFactoryLinux(ui_task_runner); | 207 return new VideoCaptureDeviceFactoryLinux(ui_task_runner); |
226 } | 208 } |
227 | 209 |
228 } // namespace media | 210 } // namespace media |
OLD | NEW |