make use of media_use_ffmpeg in BUILD.gn
[chromium-blink-merge.git] / extensions / browser / api / webcam_private / v4l2_webcam.cc
blobf6d53c50c0dbb60bc5328b89a2965587c6c9e258
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/api/webcam_private/v4l2_webcam.h"
7 #include <fcntl.h>
8 #include <linux/uvcvideo.h>
9 #include <linux/videodev2.h>
10 #include <stdio.h>
11 #include <sys/ioctl.h>
12 #include <unistd.h>
14 #include "base/posix/eintr_wrapper.h"
16 #define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32)
17 #define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33)
18 #define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE+34)
20 // GUID of the Extension Unit for Logitech CC3300e motor control:
21 // {212de5ff-3080-2c4e-82d9-f587d00540bd}
22 #define UVC_GUID_LOGITECH_CC3000E_MOTORS \
23 {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \
24 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd}
26 #define LOGITECH_MOTORCONTROL_PANTILT_CMD 2
28 namespace {
29 const int kLogitechMenuIndexGoHome = 2;
31 const uvc_menu_info kLogitechCmdMenu[] = {
32 {1, "Set Preset"}, {2, "Get Preset"}, {3, "Go Home"}
35 const uvc_xu_control_mapping kLogitechCmdMapping = {
36 V4L2_CID_PANTILT_CMD,
37 "Pan/Tilt Go",
38 UVC_GUID_LOGITECH_CC3000E_MOTORS,
39 LOGITECH_MOTORCONTROL_PANTILT_CMD,
42 V4L2_CTRL_TYPE_MENU,
43 UVC_CTRL_DATA_TYPE_ENUM,
44 const_cast<uvc_menu_info*>(&kLogitechCmdMenu[0]),
45 arraysize(kLogitechCmdMenu),
47 } // namespace
49 namespace extensions {
51 V4L2Webcam::V4L2Webcam(const std::string& device_id) : device_id_(device_id) {
54 V4L2Webcam::~V4L2Webcam() {
57 bool V4L2Webcam::Open() {
58 fd_.reset(HANDLE_EINTR(open(device_id_.c_str(), 0)));
59 return fd_.is_valid();
62 bool V4L2Webcam::EnsureLogitechCommandsMapped() {
63 int res =
64 HANDLE_EINTR(ioctl(fd_.get(), UVCIOC_CTRL_MAP, &kLogitechCmdMapping));
65 // If mapping is successful or it's already mapped, this is a Logitech
66 // camera.
67 // NOTE: On success, occasionally EFAULT is returned. On a real error,
68 // ENOMEM, EPERM, EINVAL, or EOVERFLOW should be returned.
69 return res >= 0 || errno == EEXIST || errno == EFAULT;
72 bool V4L2Webcam::SetWebcamParameter(int fd, uint32_t control_id, int value) {
73 struct v4l2_control v4l2_ctrl = {control_id, value};
74 int res = HANDLE_EINTR(ioctl(fd, VIDIOC_S_CTRL, &v4l2_ctrl)) >= 0;
75 return res >= 0;
78 bool V4L2Webcam::GetWebcamParameter(int fd, uint32_t control_id, int* value) {
79 struct v4l2_control v4l2_ctrl = {control_id};
81 if (HANDLE_EINTR(ioctl(fd, VIDIOC_G_CTRL, &v4l2_ctrl)))
82 return false;
84 *value = v4l2_ctrl.value;
85 return true;
88 void V4L2Webcam::Reset(bool pan, bool tilt, bool zoom) {
89 if (pan || tilt) {
90 if (EnsureLogitechCommandsMapped()) {
91 SetWebcamParameter(fd_.get(), V4L2_CID_PANTILT_CMD,
92 kLogitechMenuIndexGoHome);
93 } else {
94 if (pan) {
95 struct v4l2_control v4l2_ctrl = {V4L2_CID_PAN_RESET};
96 HANDLE_EINTR(ioctl(fd_.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
99 if (tilt) {
100 struct v4l2_control v4l2_ctrl = {V4L2_CID_TILT_RESET};
101 HANDLE_EINTR(ioctl(fd_.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
106 if (zoom) {
107 const int kDefaultZoom = 100;
108 SetWebcamParameter(fd_.get(), V4L2_CID_ZOOM_ABSOLUTE, kDefaultZoom);
112 bool V4L2Webcam::GetPan(int* value) {
113 return GetWebcamParameter(fd_.get(), V4L2_CID_PAN_ABSOLUTE, value);
116 bool V4L2Webcam::GetTilt(int* value) {
117 return GetWebcamParameter(fd_.get(), V4L2_CID_TILT_ABSOLUTE, value);
120 bool V4L2Webcam::GetZoom(int* value) {
121 return GetWebcamParameter(fd_.get(), V4L2_CID_ZOOM_ABSOLUTE, value);
124 bool V4L2Webcam::SetPan(int value) {
125 return SetWebcamParameter(fd_.get(), V4L2_CID_PAN_ABSOLUTE, value);
128 bool V4L2Webcam::SetTilt(int value) {
129 return SetWebcamParameter(fd_.get(), V4L2_CID_TILT_ABSOLUTE, value);
132 bool V4L2Webcam::SetZoom(int value) {
133 return SetWebcamParameter(fd_.get(), V4L2_CID_ZOOM_ABSOLUTE, value);
136 bool V4L2Webcam::SetPanDirection(PanDirection direction) {
137 int direction_value = 0;
138 switch (direction) {
139 case PAN_STOP:
140 direction_value = 0;
141 break;
143 case PAN_RIGHT:
144 direction_value = 1;
145 break;
147 case PAN_LEFT:
148 direction_value = -1;
149 break;
151 return SetWebcamParameter(fd_.get(), V4L2_CID_PAN_SPEED, direction_value);
154 bool V4L2Webcam::SetTiltDirection(TiltDirection direction) {
155 int direction_value = 0;
156 switch (direction) {
157 case TILT_STOP:
158 direction_value = 0;
159 break;
161 case TILT_UP:
162 direction_value = 1;
163 break;
165 case TILT_DOWN:
166 direction_value = -1;
167 break;
169 return SetWebcamParameter(fd_.get(), V4L2_CID_TILT_SPEED, direction_value);
172 } // namespace extensions