summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorbraveyao@chromium.org <braveyao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-03 11:01:30 +0000
committerbraveyao@chromium.org <braveyao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-03 11:01:30 +0000
commite6b79a6051f24613fbe3fe0b4fd0fe5aeaf15af6 (patch)
tree644cc7257088e3d79ece984131b81631e52c4594 /media
parent58a438a3dedfc5be85bce9b1272ffbe012ee4189 (diff)
downloadchromium_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.cc69
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;