Chromium Code Reviews| Index: media/video/capture/linux/video_capture_device_factory_linux.cc |
| diff --git a/media/video/capture/linux/video_capture_device_factory_linux.cc b/media/video/capture/linux/video_capture_device_factory_linux.cc |
| index 7e5b99ca35a7b1af68dd2be67e0683fbb7020a52..f0acfd7d1709def168d40bb2d1e180677c3789c6 100644 |
| --- a/media/video/capture/linux/video_capture_device_factory_linux.cc |
| +++ b/media/video/capture/linux/video_capture_device_factory_linux.cc |
| @@ -24,22 +24,20 @@ |
| namespace media { |
| -static bool HasUsableFormats(int fd) { |
| - v4l2_fmtdesc fmtdesc; |
| - std::list<int> usable_fourccs; |
| +static int Ioctl(const base::ScopedFD& device_fd, int request, void* arg) { |
| + return VideoCaptureDeviceLinux::Ioctl(device_fd, request, arg); |
| +} |
| - media::VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false, |
| - &usable_fourccs); |
| +static bool HasUsableFormats(const base::ScopedFD& device_fd) { |
| + const std::list<int>& usable_fourccs = |
| + VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false); |
| - memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc)); |
| + v4l2_fmtdesc fmtdesc = {}; |
| fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| - |
| - while (HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) { |
| + for (; Ioctl(device_fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { |
| if (std::find(usable_fourccs.begin(), usable_fourccs.end(), |
| fmtdesc.pixelformat) != usable_fourccs.end()) |
| return true; |
| - |
| - fmtdesc.index++; |
| } |
| return false; |
| } |
| @@ -80,32 +78,28 @@ void VideoCaptureDeviceFactoryLinux::GetDeviceNames( |
| VideoCaptureDevice::Names* const device_names) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(device_names->empty()); |
| - base::FilePath path("/dev/"); |
| + const base::FilePath path("/dev/"); |
| base::FileEnumerator enumerator( |
| path, false, base::FileEnumerator::FILES, "video*"); |
| while (!enumerator.Next().empty()) { |
| - base::FileEnumerator::FileInfo info = enumerator.GetInfo(); |
| - |
| - std::string unique_id = path.value() + info.GetName().value(); |
| - base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY))); |
| + const base::FileEnumerator::FileInfo info = enumerator.GetInfo(); |
| + const std::string unique_id = path.value() + info.GetName().value(); |
| + const base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY))); |
| if (!fd.is_valid()) { |
| - // Failed to open this device. |
| + DLOG(ERROR) << "Couldn't open " << info.GetName().value(); |
| continue; |
| } |
| - // Test if this is a V4L2 capture device. |
| + // Test if this is a V4L2 capture device and if it has at least one |
| + // supported capture format. Single plane capture devices should not be |
| + // 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.
|
| v4l2_capability cap; |
| - if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) && |
| - (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && |
| - !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { |
| - // This is a V4L2 video capture device |
| - if (HasUsableFormats(fd.get())) { |
| - VideoCaptureDevice::Name device_name(base::StringPrintf("%s", cap.card), |
| - unique_id); |
| - device_names->push_back(device_name); |
| - } else { |
| - DVLOG(1) << "No usable formats reported by " << info.GetName().value(); |
| - } |
| + if ((Ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) && |
| + (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE && |
| + !(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.
|
| + HasUsableFormats(fd)) { |
| + device_names->push_front(VideoCaptureDevice::Name( |
| + base::StringPrintf("%s", cap.card), unique_id)); |
| } |
| } |
| } |
| @@ -117,80 +111,65 @@ void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats( |
| if (device.id().empty()) |
| return; |
| base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))); |
| - if (!fd.is_valid()) { |
| - // Failed to open this device. |
| + if (!fd.is_valid()) // Failed to open this device. |
| return; |
| - } |
| supported_formats->clear(); |
| // Retrieve the caps one by one, first get pixel format, then sizes, then |
| - // frame rates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference. |
| + // frame rates. |
| v4l2_fmtdesc pixel_format = {}; |
| pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| - while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FMT, &pixel_format)) == 0) { |
| + for (; Ioctl(fd, VIDIOC_ENUM_FMT, &pixel_format) == 0; ++pixel_format.index) { |
| VideoCaptureFormat supported_format; |
| supported_format.pixel_format = |
| - VideoCaptureDeviceLinux::V4l2ColorToVideoCaptureColorFormat( |
| - (int32)pixel_format.pixelformat); |
| - if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) { |
| - ++pixel_format.index; |
| + VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat( |
| + pixel_format.pixelformat); |
| + if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) |
| continue; |
| - } |
| v4l2_frmsizeenum frame_size = {}; |
| frame_size.pixel_format = pixel_format.pixelformat; |
| - while (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FRAMESIZES, &frame_size)) == |
| - 0) { |
| + for (; Ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0; |
| + ++frame_size.index) { |
| if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { |
| supported_format.frame_size.SetSize( |
| frame_size.discrete.width, frame_size.discrete.height); |
| - } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { |
| - // TODO(mcasas): see http://crbug.com/249953, support these devices. |
| - NOTIMPLEMENTED(); |
| - } else if (frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { |
| + } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE || |
| + frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { |
| // TODO(mcasas): see http://crbug.com/249953, support these devices. |
| NOTIMPLEMENTED(); |
| } |
| + |
| v4l2_frmivalenum frame_interval = {}; |
| frame_interval.pixel_format = pixel_format.pixelformat; |
| frame_interval.width = frame_size.discrete.width; |
| frame_interval.height = frame_size.discrete.height; |
| std::list<float> frame_rates; |
| - while (HANDLE_EINTR(ioctl( |
| - fd.get(), VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0) { |
| + for (; Ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval) == 0; |
| + ++frame_interval.index) { |
|
perkj_chrome
2014/12/16 10:34:43
nit indentation.
mcasas
2014/12/16 18:08:17
Done.
|
| if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) { |
| if (frame_interval.discrete.numerator != 0) { |
| - frame_rates.push_back( |
| - static_cast<float>(frame_interval.discrete.denominator) / |
| + frame_rates.push_back(frame_interval.discrete.denominator / |
| static_cast<float>(frame_interval.discrete.numerator)); |
| } |
| - } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { |
| - // TODO(mcasas): see http://crbug.com/249953, support these devices. |
| - NOTIMPLEMENTED(); |
| - break; |
| - } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) { |
| + } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS || |
| + frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) { |
| // TODO(mcasas): see http://crbug.com/249953, support these devices. |
| NOTIMPLEMENTED(); |
| break; |
| } |
| - ++frame_interval.index; |
| } |
| - |
| - // Some devices, e.g. Kinect, do not enumerate any frame rates. For these |
| - // devices, we do not want to lose all enumeration (pixel format and |
| - // resolution), so we return a frame rate of zero instead. |
| + // Some devices, e.g. Kinect, do not enumerate any frame rates, see |
| + // http://crbug.com/412284. Set their frame_rate to zero. |
| if (frame_rates.empty()) |
| - frame_rates.push_back(0); |
| + frame_rates.push_back(0.0f); |
| - for (std::list<float>::iterator it = frame_rates.begin(); |
| - it != frame_rates.end(); ++it) { |
| - supported_format.frame_rate = *it; |
| + for (const auto& it : frame_rates) { |
| + supported_format.frame_rate = it; |
| supported_formats->push_back(supported_format); |
| DVLOG(1) << device.name() << " " << supported_format.ToString(); |
| } |
| - ++frame_size.index; |
| } |
| - ++pixel_format.index; |
| } |
| return; |
| } |