| 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 |