diff options
author | braveyao@chromium.org <braveyao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-03 11:01:30 +0000 |
---|---|---|
committer | braveyao@chromium.org <braveyao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-03 11:01:30 +0000 |
commit | e6b79a6051f24613fbe3fe0b4fd0fe5aeaf15af6 (patch) | |
tree | 644cc7257088e3d79ece984131b81631e52c4594 /media | |
parent | 58a438a3dedfc5be85bce9b1272ffbe012ee4189 (diff) | |
download | chromium_src-e6b79a6051f24613fbe3fe0b4fd0fe5aeaf15af6.zip chromium_src-e6b79a6051f24613fbe3fe0b4fd0fe5aeaf15af6.tar.gz chromium_src-e6b79a6051f24613fbe3fe0b4fd0fe5aeaf15af6.tar.bz2 |
To enumerate webcams on Linux more robustically
BUG=178359
TEST=media_unittests
Review URL: https://chromiumcodereview.appspot.com/13056002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192048 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/video/capture/linux/video_capture_device_linux.cc | 69 |
1 files changed, 28 insertions, 41 deletions
diff --git a/media/video/capture/linux/video_capture_device_linux.cc b/media/video/capture/linux/video_capture_device_linux.cc index 3350867..e47eac3 100644 --- a/media/video/capture/linux/video_capture_device_linux.cc +++ b/media/video/capture/linux/video_capture_device_linux.cc @@ -21,20 +21,6 @@ #include "base/file_util.h" #include "base/stringprintf.h" -// Workaround for some device. This query of all controls magically brings -// device back to normal from bad state. -// See http://crbug.com/94134. -static void ResetCameraByEnumeratingIoctlsHACK(int fd) { - struct v4l2_queryctrl query_ctrl; - memset(&query_ctrl, 0, sizeof(query_ctrl)); - - for (query_ctrl.id = V4L2_CID_BASE; - query_ctrl.id < V4L2_CID_LASTP1; - query_ctrl.id++) { - ioctl(fd, VIDIOC_QUERYCTRL, &query_ctrl); - } -} - namespace media { // Max number of video buffers VideoCaptureDeviceLinux can allocate. @@ -67,7 +53,9 @@ static VideoCaptureCapability::Format V4l2ColorToVideoCaptureColorFormat( result = VideoCaptureCapability::kYUY2; break; case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: result = VideoCaptureCapability::kMJPEG; + break; } DCHECK_NE(result, VideoCaptureCapability::kColorUnknown); return result; @@ -80,6 +68,10 @@ static void GetListOfUsableFourCCs(bool favour_mjpeg, std::list<int>* fourccs) { fourccs->push_front(V4L2_PIX_FMT_MJPEG); else fourccs->push_back(V4L2_PIX_FMT_MJPEG); + + // JPEG works as MJPEG on some gspca webcams from field reports. + // Put it as the least preferred format. + fourccs->push_back(V4L2_PIX_FMT_JPEG); } static bool HasUsableFormats(int fd) { @@ -257,42 +249,37 @@ void VideoCaptureDeviceLinux::OnAllocate(int width, return; } - v4l2_format video_fmt; - memset(&video_fmt, 0, sizeof(video_fmt)); - video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - video_fmt.fmt.pix.sizeimage = 0; - video_fmt.fmt.pix.width = width; - video_fmt.fmt.pix.height = height; - - // Some device failed in first VIDIOC_TRY_FMT with EBUSY or EIO. - // But second VIDIOC_TRY_FMT succeeds. - // See http://crbug.com/94134. - bool format_match = false; - std::list<int> v4l2_formats; - + // Get supported video formats in preferred order. // For large resolutions, favour mjpeg over raw formats. + std::list<int> v4l2_formats; GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight, &v4l2_formats); - for (std::list<int>::const_iterator it = v4l2_formats.begin(); - it != v4l2_formats.end() && !format_match; ++it) { - video_fmt.fmt.pix.pixelformat = *it; - for (int attempt = 0; attempt < 2 && !format_match; ++attempt) { - ResetCameraByEnumeratingIoctlsHACK(device_fd_); - if (ioctl(device_fd_, VIDIOC_TRY_FMT, &video_fmt) < 0) { - if (errno != EIO) - break; - } else { - format_match = true; - } - } + v4l2_fmtdesc fmtdesc; + memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc)); + fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + // Enumerate image formats. + std::list<int>::iterator best = v4l2_formats.end(); + while (ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { + best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat); + fmtdesc.index++; } - if (!format_match) { - SetErrorState("Failed to find supported camera format."); + if (best == v4l2_formats.end()) { + SetErrorState("Failed to find a supported camera format."); return; } + // Set format and frame size now. + v4l2_format video_fmt; + memset(&video_fmt, 0, sizeof(video_fmt)); + video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + video_fmt.fmt.pix.sizeimage = 0; + video_fmt.fmt.pix.width = width; + video_fmt.fmt.pix.height = height; + video_fmt.fmt.pix.pixelformat = *best; + if (ioctl(device_fd_, VIDIOC_S_FMT, &video_fmt) < 0) { SetErrorState("Failed to set camera format"); return; |