Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc

Issue 1136883004: Move V4L2 code into a webcam helper class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/browser/api/webcam_private/webcam_private_api.h" 5 #include "extensions/browser/api/webcam_private/webcam_private_api.h"
6 6
7 #include <fcntl.h> 7 #include "base/lazy_instance.h"
8 #include <linux/uvcvideo.h>
9 #include <linux/videodev2.h>
10 #include <stdio.h>
11 #include <sys/ioctl.h>
12 #include <unistd.h>
13
14 #include "base/files/scoped_file.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "content/public/browser/browser_context.h" 8 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/media_device_id.h" 9 #include "content/public/browser/media_device_id.h"
18 #include "content/public/browser/resource_context.h" 10 #include "content/public/browser/resource_context.h"
19 #include "content/public/common/media_stream_request.h" 11 #include "content/public/common/media_stream_request.h"
12 #include "extensions/browser/api/webcam_private/v4l2_webcam.h"
13 #include "extensions/browser/api/webcam_private/webcam.h"
14 #include "extensions/browser/process_manager.h"
15 #include "extensions/browser/process_manager_factory.h"
20 #include "extensions/common/api/webcam_private.h" 16 #include "extensions/common/api/webcam_private.h"
21 17
22 #define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE+32)
23 #define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE+33)
24 #define V4L2_CID_PANTILT_CMD (V4L2_CID_CAMERA_CLASS_BASE+34)
25
26 // GUID of the Extension Unit for Logitech CC3300e motor control:
27 // {212de5ff-3080-2c4e-82d9-f587d00540bd}
28 #define UVC_GUID_LOGITECH_CC3000E_MOTORS \
29 {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \
30 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd}
31
32 #define LOGITECH_MOTORCONTROL_PANTILT_CMD 2
33
34 namespace webcam_private = extensions::core_api::webcam_private; 18 namespace webcam_private = extensions::core_api::webcam_private;
35 19
36 namespace content { 20 namespace content {
37 class BrowserContext; 21 class BrowserContext;
38 } // namespace content 22 } // namespace content
39 23
40 namespace { 24 namespace {
41 const int kLogitechMenuIndexGoHome = 2;
42
43 const uvc_menu_info kLogitechCmdMenu[] = {
44 {1, "Set Preset"}, {2, "Get Preset"}, {3, "Go Home"}
45 };
46
47 const uvc_xu_control_mapping kLogitechCmdMapping = {
48 V4L2_CID_PANTILT_CMD,
49 "Pan/Tilt Go",
50 UVC_GUID_LOGITECH_CC3000E_MOTORS,
51 LOGITECH_MOTORCONTROL_PANTILT_CMD,
52 8,
53 0,
54 V4L2_CTRL_TYPE_MENU,
55 UVC_CTRL_DATA_TYPE_ENUM,
56 const_cast<uvc_menu_info*>(&kLogitechCmdMenu[0]),
57 arraysize(kLogitechCmdMenu),
58 };
59
60 base::ScopedFD OpenWebcam(const std::string& extension_id,
61 content::BrowserContext* browser_context,
62 const std::string& webcam_id) {
63 GURL security_origin =
64 extensions::Extension::GetBaseURLFromExtensionId(extension_id);
65
66 std::string device_id;
67 bool success = content::GetMediaDeviceIDForHMAC(
68 content::MEDIA_DEVICE_VIDEO_CAPTURE,
69 browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
70 security_origin,
71 webcam_id,
72 &device_id);
73
74 if (!success)
75 return base::ScopedFD();
76
77 return base::ScopedFD(HANDLE_EINTR(open(device_id.c_str(), 0)));
78 }
79
80 void SetWebcamParameter(int fd, uint32_t control_id, int value) {
81 struct v4l2_control v4l2_ctrl = {control_id, value};
82 HANDLE_EINTR(ioctl(fd, VIDIOC_S_CTRL, &v4l2_ctrl));
83 }
84
85 bool GetWebcamParameter(int fd, uint32_t control_id, int* value) {
86 struct v4l2_control v4l2_ctrl = {control_id};
87
88 if (HANDLE_EINTR(ioctl(fd, VIDIOC_G_CTRL, &v4l2_ctrl)))
89 return false;
90
91 *value = v4l2_ctrl.value;
92 return true;
93 }
94
95 bool EnsureLogitechCommandsMapped(int fd) {
96 int res = ioctl(fd, UVCIOC_CTRL_MAP, &kLogitechCmdMapping);
97 // If mapping is successful or it's already mapped, this is a Logitech camera.
98 return res >= 0 || errno == EEXIST;
99 }
100
101 const char kUnknownWebcam[] = "Unknown webcam id"; 25 const char kUnknownWebcam[] = "Unknown webcam id";
102 } // namespace 26 } // namespace
103 27
104 namespace extensions { 28 namespace extensions {
105 29
30 // static
31 WebcamPrivateAPI* WebcamPrivateAPI::Get(content::BrowserContext* context) {
32 return GetFactoryInstance()->Get(context);
33 }
34
35 WebcamPrivateAPI::WebcamPrivateAPI(content::BrowserContext* context)
36 : browser_context_(context),
37 process_manager_observer_(this),
38 weak_ptr_factory_(this) {
39 process_manager_observer_.Add(ProcessManager::Get(browser_context_));
40 }
41
42 WebcamPrivateAPI::~WebcamPrivateAPI() {}
43
44 Webcam* WebcamPrivateAPI::GetWebcam(const std::string& extension_id,
45 const std::string& webcam_id) {
46 std::string device_id;
47 if (!GetDeviceId(extension_id, webcam_id, &device_id)) {
48 return nullptr;
49 }
50
51 auto ix = webcams_.find(device_id);
52 if (ix != webcams_.end()) {
53 ix->second->AddExtensionRef(extension_id);
54 return ix->second.get();
55 }
56
57 scoped_ptr<V4L2Webcam> v4l2_webcam(new V4L2Webcam(device_id));
58 if (!v4l2_webcam->Open()) {
59 return nullptr;
60 }
61
62 linked_ptr<Webcam> webcam(v4l2_webcam.release());
63
64 webcams_[device_id] = webcam;
65 webcam->AddExtensionRef(extension_id);
66
67 return webcam.get();
68 }
69
70 bool WebcamPrivateAPI::GetDeviceId(const std::string& extension_id,
71 const std::string& webcam_id,
72 std::string* device_id) {
73 GURL security_origin =
74 extensions::Extension::GetBaseURLFromExtensionId(extension_id);
75
76 return content::GetMediaDeviceIDForHMAC(
77 content::MEDIA_DEVICE_VIDEO_CAPTURE,
78 browser_context_->GetResourceContext()->GetMediaDeviceIDSalt(),
79 security_origin,
80 webcam_id,
81 device_id);
82 }
83
84 void WebcamPrivateAPI::OnBackgroundHostClose(const std::string& extension_id) {
85 for (auto webcam = webcams_.begin();
86 webcam != webcams_.end(); /* No increment */ ) {
87 auto next = std::next(webcam);
88 webcam->second->RemoveExtensionRef(extension_id);
89 if (webcam->second->ShouldDelete())
90 webcams_.erase(webcam);
91 webcam = next;
92 }
93 }
94
106 WebcamPrivateSetFunction::WebcamPrivateSetFunction() { 95 WebcamPrivateSetFunction::WebcamPrivateSetFunction() {
107 } 96 }
108 97
109 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() { 98 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() {
110 } 99 }
111 100
112 bool WebcamPrivateSetFunction::RunSync() { 101 bool WebcamPrivateSetFunction::RunSync() {
113 // Get parameters 102 // Get parameters
114 scoped_ptr<webcam_private::Set::Params> params( 103 scoped_ptr<webcam_private::Set::Params> params(
115 webcam_private::Set::Params::Create(*args_)); 104 webcam_private::Set::Params::Create(*args_));
116 EXTENSION_FUNCTION_VALIDATE(params.get()); 105 EXTENSION_FUNCTION_VALIDATE(params.get());
117 106
118 base::ScopedFD fd = 107 Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
119 OpenWebcam(extension_id(), browser_context(), params->webcam_id); 108 GetWebcam(extension_id(), params->webcam_id);
120 if (!fd.is_valid()) { 109 if (!webcam) {
121 SetError(kUnknownWebcam); 110 SetError(kUnknownWebcam);
122 return false; 111 return false;
123 } 112 }
124 113
125 if (params->config.pan) { 114 if (params->config.pan) {
126 SetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE, 115 webcam->SetPan(*(params->config.pan));
127 *(params->config.pan));
128 } 116 }
129 117
130 if (params->config.pan_direction) { 118 if (params->config.pan_direction) {
131 int direction = 0; 119 Webcam::PanDirection direction = Webcam::PAN_STOP;
132 switch (params->config.pan_direction) { 120 switch (params->config.pan_direction) {
133 case webcam_private::PAN_DIRECTION_NONE: 121 case webcam_private::PAN_DIRECTION_NONE:
134 case webcam_private::PAN_DIRECTION_STOP: 122 case webcam_private::PAN_DIRECTION_STOP:
135 direction = 0; 123 direction = Webcam::PAN_STOP;
136 break; 124 break;
137 125
138 case webcam_private::PAN_DIRECTION_RIGHT: 126 case webcam_private::PAN_DIRECTION_RIGHT:
139 direction = 1; 127 direction = Webcam::PAN_RIGHT;
140 break; 128 break;
141 129
142 case webcam_private::PAN_DIRECTION_LEFT: 130 case webcam_private::PAN_DIRECTION_LEFT:
143 direction = -1; 131 direction = Webcam::PAN_LEFT;
144 break; 132 break;
145 } 133 }
146 SetWebcamParameter(fd.get(), V4L2_CID_PAN_SPEED, direction); 134 webcam->SetPanDirection(direction);
147 } 135 }
148 136
149 if (params->config.tilt) { 137 if (params->config.tilt) {
150 SetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE, 138 webcam->SetTilt(*(params->config.tilt));
151 *(params->config.tilt));
152 } 139 }
153 140
154 if (params->config.tilt_direction) { 141 if (params->config.tilt_direction) {
155 int direction = 0; 142 Webcam::TiltDirection direction = Webcam::TILT_STOP;
156 switch (params->config.tilt_direction) { 143 switch (params->config.tilt_direction) {
157 case webcam_private::TILT_DIRECTION_NONE: 144 case webcam_private::TILT_DIRECTION_NONE:
158 case webcam_private::TILT_DIRECTION_STOP: 145 case webcam_private::TILT_DIRECTION_STOP:
159 direction = 0; 146 direction = Webcam::TILT_STOP;
160 break; 147 break;
161 148
162 case webcam_private::TILT_DIRECTION_UP: 149 case webcam_private::TILT_DIRECTION_UP:
163 direction = 1; 150 direction = Webcam::TILT_UP;
164 break; 151 break;
165 152
166 case webcam_private::TILT_DIRECTION_DOWN: 153 case webcam_private::TILT_DIRECTION_DOWN:
167 direction = -1; 154 direction = Webcam::TILT_DOWN;
168 break; 155 break;
169 } 156 }
170 SetWebcamParameter(fd.get(), V4L2_CID_TILT_SPEED, direction); 157 webcam->SetTiltDirection(direction);
171 } 158 }
172 159
173 if (params->config.zoom) { 160 if (params->config.zoom) {
174 SetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, 161 webcam->SetZoom(*(params->config.zoom));
175 *(params->config.zoom));
176 } 162 }
177 163
178 164
179 return true; 165 return true;
180 } 166 }
181 167
182 WebcamPrivateGetFunction::WebcamPrivateGetFunction() { 168 WebcamPrivateGetFunction::WebcamPrivateGetFunction() {
183 } 169 }
184 170
185 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() { 171 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() {
186 } 172 }
187 173
188 bool WebcamPrivateGetFunction::RunSync() { 174 bool WebcamPrivateGetFunction::RunSync() {
189 // Get parameters 175 // Get parameters
190 scoped_ptr<webcam_private::Get::Params> params( 176 scoped_ptr<webcam_private::Get::Params> params(
191 webcam_private::Get::Params::Create(*args_)); 177 webcam_private::Get::Params::Create(*args_));
192 EXTENSION_FUNCTION_VALIDATE(params.get()); 178 EXTENSION_FUNCTION_VALIDATE(params.get());
193 179
194 base::ScopedFD fd = 180 Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
195 OpenWebcam(extension_id(), browser_context(), params->webcam_id); 181 GetWebcam(extension_id(), params->webcam_id);
196 if (!fd.is_valid()) { 182 if (!webcam) {
197 SetError(kUnknownWebcam); 183 SetError(kUnknownWebcam);
198 return false; 184 return false;
199 } 185 }
200 186
201 webcam_private::WebcamConfiguration result; 187 webcam_private::WebcamConfiguration result;
202 188
203 int pan; 189 int pan;
204 if (GetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE, &pan)) 190 if (webcam->GetPan(&pan))
205 result.pan.reset(new double(pan)); 191 result.pan.reset(new double(pan));
206 192
207 int tilt; 193 int tilt;
208 if (GetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE, &tilt)) 194 if (webcam->GetTilt(&tilt))
209 result.tilt.reset(new double(tilt)); 195 result.tilt.reset(new double(tilt));
210 196
211 int zoom; 197 int zoom;
212 if (GetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, &zoom)) 198 if (webcam->GetZoom(&zoom))
213 result.zoom.reset(new double(zoom)); 199 result.zoom.reset(new double(zoom));
214 200
215 SetResult(result.ToValue().release()); 201 SetResult(result.ToValue().release());
216 202
217 return true; 203 return true;
218 } 204 }
219 205
220 WebcamPrivateResetFunction::WebcamPrivateResetFunction() { 206 WebcamPrivateResetFunction::WebcamPrivateResetFunction() {
221 } 207 }
222 208
223 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() { 209 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() {
224 } 210 }
225 211
226 bool WebcamPrivateResetFunction::RunSync() { 212 bool WebcamPrivateResetFunction::RunSync() {
227 // Get parameters 213 // Get parameters
228 scoped_ptr<webcam_private::Reset::Params> params( 214 scoped_ptr<webcam_private::Reset::Params> params(
229 webcam_private::Reset::Params::Create(*args_)); 215 webcam_private::Reset::Params::Create(*args_));
230 EXTENSION_FUNCTION_VALIDATE(params.get()); 216 EXTENSION_FUNCTION_VALIDATE(params.get());
231 217
232 base::ScopedFD fd = 218 Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
233 OpenWebcam(extension_id(), browser_context(), params->webcam_id); 219 GetWebcam(extension_id(), params->webcam_id);
234 if (!fd.is_valid()) { 220 if (!webcam) {
235 SetError(kUnknownWebcam); 221 SetError(kUnknownWebcam);
236 return false; 222 return false;
237 } 223 }
238 224
239 if (params->config.pan || params->config.tilt) { 225 webcam->Reset(params->config.pan, params->config.tilt, params->config.zoom);
240 if (EnsureLogitechCommandsMapped(fd.get())) {
241 SetWebcamParameter(fd.get(), V4L2_CID_PANTILT_CMD,
242 kLogitechMenuIndexGoHome);
243 }
244 }
245
246 if (params->config.pan) {
247 struct v4l2_control v4l2_ctrl = {V4L2_CID_PAN_RESET};
248 HANDLE_EINTR(ioctl(fd.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
249 }
250
251 if (params->config.tilt) {
252 struct v4l2_control v4l2_ctrl = {V4L2_CID_TILT_RESET};
253 HANDLE_EINTR(ioctl(fd.get(), VIDIOC_S_CTRL, &v4l2_ctrl));
254 }
255
256 if (params->config.zoom) {
257 const int kDefaultZoom = 100;
258 SetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, kDefaultZoom);
259 }
260 226
261 return true; 227 return true;
262 } 228 }
263 229
230 static base::LazyInstance<BrowserContextKeyedAPIFactory<WebcamPrivateAPI>>
231 g_factory = LAZY_INSTANCE_INITIALIZER;
232
233 // static
234 BrowserContextKeyedAPIFactory<WebcamPrivateAPI>*
235 WebcamPrivateAPI::GetFactoryInstance() {
236 return g_factory.Pointer();
237 }
238
239 template <>
240 void BrowserContextKeyedAPIFactory<WebcamPrivateAPI>
241 ::DeclareFactoryDependencies() {
242 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
243 DependsOn(ProcessManagerFactory::GetInstance());
244 }
245
264 } // namespace extensions 246 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698