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
3 // found in the LICENSE file.
5 #include "extensions/browser/api/webcam_private/webcam_private_api.h"
8 #include <linux/videodev2.h>
10 #include <sys/ioctl.h>
13 #include "base/files/scoped_file.h"
14 #include "base/posix/eintr_wrapper.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/media_device_id.h"
17 #include "content/public/browser/resource_context.h"
18 #include "content/public/common/media_stream_request.h"
19 #include "extensions/common/api/webcam_private.h"
21 #define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32)
22 #define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33)
24 namespace webcam_private
= extensions::core_api::webcam_private
;
28 } // namespace content
32 base::ScopedFD
OpenWebcam(const std::string
& extension_id
,
33 content::BrowserContext
* browser_context
,
34 const std::string
& webcam_id
) {
35 GURL security_origin
=
36 extensions::Extension::GetBaseURLFromExtensionId(extension_id
);
38 std::string device_id
;
39 bool success
= content::GetMediaDeviceIDForHMAC(
40 content::MEDIA_DEVICE_VIDEO_CAPTURE
,
41 browser_context
->GetResourceContext()->GetMediaDeviceIDSalt(),
47 return base::ScopedFD();
49 return base::ScopedFD(HANDLE_EINTR(open(device_id
.c_str(), 0)));
52 void SetWebcamParameter(int fd
, uint32_t control_id
, int value
) {
53 struct v4l2_control v4l2_ctrl
= {control_id
, value
};
54 HANDLE_EINTR(ioctl(fd
, VIDIOC_S_CTRL
, &v4l2_ctrl
));
57 bool GetWebcamParameter(int fd
, uint32_t control_id
, int* value
) {
58 struct v4l2_control v4l2_ctrl
= {control_id
};
60 if (HANDLE_EINTR(ioctl(fd
, VIDIOC_G_CTRL
, &v4l2_ctrl
)))
63 *value
= v4l2_ctrl
.value
;
67 const char kUnknownWebcam
[] = "Unknown webcam id";
70 namespace extensions
{
72 WebcamPrivateSetFunction::WebcamPrivateSetFunction() {
75 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() {
78 bool WebcamPrivateSetFunction::RunSync() {
80 scoped_ptr
<webcam_private::Set::Params
> params(
81 webcam_private::Set::Params::Create(*args_
));
82 EXTENSION_FUNCTION_VALIDATE(params
.get());
85 OpenWebcam(extension_id(), browser_context(), params
->webcam_id
);
87 SetError(kUnknownWebcam
);
91 if (params
->config
.pan
) {
92 SetWebcamParameter(fd
.get(), V4L2_CID_PAN_ABSOLUTE
,
93 *(params
->config
.pan
));
96 if (params
->config
.pan_direction
) {
98 switch (params
->config
.pan_direction
) {
99 case webcam_private::PAN_DIRECTION_NONE
:
100 case webcam_private::PAN_DIRECTION_STOP
:
104 case webcam_private::PAN_DIRECTION_RIGHT
:
108 case webcam_private::PAN_DIRECTION_LEFT
:
112 SetWebcamParameter(fd
.get(), V4L2_CID_PAN_SPEED
, direction
);
115 if (params
->config
.tilt
) {
116 SetWebcamParameter(fd
.get(), V4L2_CID_TILT_ABSOLUTE
,
117 *(params
->config
.tilt
));
120 if (params
->config
.tilt_direction
) {
122 switch (params
->config
.tilt_direction
) {
123 case webcam_private::TILT_DIRECTION_NONE
:
124 case webcam_private::TILT_DIRECTION_STOP
:
128 case webcam_private::TILT_DIRECTION_UP
:
132 case webcam_private::TILT_DIRECTION_DOWN
:
136 SetWebcamParameter(fd
.get(), V4L2_CID_TILT_SPEED
, direction
);
139 if (params
->config
.zoom
) {
140 SetWebcamParameter(fd
.get(), V4L2_CID_ZOOM_ABSOLUTE
,
141 *(params
->config
.zoom
));
148 WebcamPrivateGetFunction::WebcamPrivateGetFunction() {
151 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() {
154 bool WebcamPrivateGetFunction::RunSync() {
156 scoped_ptr
<webcam_private::Get::Params
> params(
157 webcam_private::Get::Params::Create(*args_
));
158 EXTENSION_FUNCTION_VALIDATE(params
.get());
161 OpenWebcam(extension_id(), browser_context(), params
->webcam_id
);
162 if (!fd
.is_valid()) {
163 SetError(kUnknownWebcam
);
167 webcam_private::WebcamConfiguration result
;
170 if (GetWebcamParameter(fd
.get(), V4L2_CID_PAN_ABSOLUTE
, &pan
))
171 result
.pan
.reset(new double(pan
));
174 if (GetWebcamParameter(fd
.get(), V4L2_CID_TILT_ABSOLUTE
, &tilt
))
175 result
.tilt
.reset(new double(tilt
));
178 if (GetWebcamParameter(fd
.get(), V4L2_CID_ZOOM_ABSOLUTE
, &zoom
))
179 result
.zoom
.reset(new double(zoom
));
181 SetResult(result
.ToValue().release());
186 WebcamPrivateResetFunction::WebcamPrivateResetFunction() {
189 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() {
192 bool WebcamPrivateResetFunction::RunSync() {
194 scoped_ptr
<webcam_private::Reset::Params
> params(
195 webcam_private::Reset::Params::Create(*args_
));
196 EXTENSION_FUNCTION_VALIDATE(params
.get());
199 OpenWebcam(extension_id(), browser_context(), params
->webcam_id
);
200 if (!fd
.is_valid()) {
201 SetError(kUnknownWebcam
);
205 if (params
->config
.pan
) {
206 struct v4l2_control v4l2_ctrl
= {V4L2_CID_PAN_RESET
};
207 HANDLE_EINTR(ioctl(fd
.get(), VIDIOC_S_CTRL
, &v4l2_ctrl
));
210 if (params
->config
.tilt
) {
211 struct v4l2_control v4l2_ctrl
= {V4L2_CID_TILT_RESET
};
212 HANDLE_EINTR(ioctl(fd
.get(), VIDIOC_S_CTRL
, &v4l2_ctrl
));
215 if (params
->config
.zoom
) {
216 const int kDefaultZoom
= 100;
217 SetWebcamParameter(fd
.get(), V4L2_CID_ZOOM_ABSOLUTE
, kDefaultZoom
);
223 } // namespace extensions