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

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: Fix move detection 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
« no previous file with comments | « extensions/browser/api/webcam_private/webcam_private_api.h ('k') | extensions/extensions.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
20 #include "extensions/common/api/webcam_private.h" 15 #include "extensions/common/api/webcam_private.h"
21 16
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; 17 namespace webcam_private = extensions::core_api::webcam_private;
35 18
36 namespace content { 19 namespace content {
37 class BrowserContext; 20 class BrowserContext;
38 } // namespace content 21 } // namespace content
39 22
40 namespace { 23 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"; 24 const char kUnknownWebcam[] = "Unknown webcam id";
102 } // namespace 25 } // namespace
103 26
104 namespace extensions { 27 namespace extensions {
105 28
29 // static
30 WebcamPrivateAPI* WebcamPrivateAPI::Get(content::BrowserContext* context) {
31 return GetFactoryInstance()->Get(context);
32 }
33
34 WebcamPrivateAPI::WebcamPrivateAPI(content::BrowserContext* context)
35 : browser_context_(context),
36 process_manager_observer_(this),
37 weak_ptr_factory_(this) {
38 process_manager_observer_.Add(ProcessManager::Get(browser_context_));
39 }
40
41 WebcamPrivateAPI::~WebcamPrivateAPI() {}
42
43 Webcam* WebcamPrivateAPI::GetWebcam(const std::string& extension_id,
44 const std::string& webcam_id) {
45 std::string device_id;
46 if (!GetDeviceId(extension_id, webcam_id, &device_id)) {
47 return nullptr;
48 }
49
50 auto ix = webcams_.find(device_id);
51 if (ix != webcams_.end()) {
52 ix->second->AddExtensionRef(extension_id);
53 return ix->second.get();
54 }
55
56 scoped_ptr<V4L2Webcam> v4l2_webcam(new V4L2Webcam(device_id));
57 if (!v4l2_webcam->Open()) {
58 return nullptr;
59 }
60
61 linked_ptr<Webcam> webcam(v4l2_webcam.release());
62
63 webcams_[device_id] = webcam;
64 webcam->AddExtensionRef(extension_id);
65
66 return webcam.get();
67 }
68
69 bool WebcamPrivateAPI::GetDeviceId(const std::string& extension_id,
70 const std::string& webcam_id,
71 std::string* device_id) {
72 GURL security_origin =
73 extensions::Extension::GetBaseURLFromExtensionId(extension_id);
74
75 return content::GetMediaDeviceIDForHMAC(
76 content::MEDIA_DEVICE_VIDEO_CAPTURE,
77 browser_context_->GetResourceContext()->GetMediaDeviceIDSalt(),
78 security_origin,
79 webcam_id,
80 device_id);
81 }
82
83 void WebcamPrivateAPI::OnBackgroundHostClose(const std::string& extension_id) {
84 for (auto webcam = webcams_.begin();
85 webcam != webcams_.end(); /* No increment */ ) {
86 auto next = std::next(webcam);
87 webcam->second->RemoveExtensionRef(extension_id);
88 if (webcam->second->ShouldDelete())
89 webcams_.erase(webcam);
90 webcam = next;
91 }
92 }
93
106 WebcamPrivateSetFunction::WebcamPrivateSetFunction() { 94 WebcamPrivateSetFunction::WebcamPrivateSetFunction() {
107 } 95 }
108 96
109 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() { 97 WebcamPrivateSetFunction::~WebcamPrivateSetFunction() {
110 } 98 }
111 99
112 bool WebcamPrivateSetFunction::RunSync() { 100 bool WebcamPrivateSetFunction::RunSync() {
113 // Get parameters 101 // Get parameters
114 scoped_ptr<webcam_private::Set::Params> params( 102 scoped_ptr<webcam_private::Set::Params> params(
115 webcam_private::Set::Params::Create(*args_)); 103 webcam_private::Set::Params::Create(*args_));
116 EXTENSION_FUNCTION_VALIDATE(params.get()); 104 EXTENSION_FUNCTION_VALIDATE(params.get());
117 105
118 base::ScopedFD fd = 106 Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
119 OpenWebcam(extension_id(), browser_context(), params->webcam_id); 107 GetWebcam(extension_id(), params->webcam_id);
120 if (!fd.is_valid()) { 108 if (!webcam) {
121 SetError(kUnknownWebcam); 109 SetError(kUnknownWebcam);
122 return false; 110 return false;
123 } 111 }
124 112
125 if (params->config.pan) { 113 if (params->config.pan) {
126 SetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE, 114 webcam->SetPan(*(params->config.pan));
127 *(params->config.pan));
128 } 115 }
129 116
130 if (params->config.pan_direction) { 117 if (params->config.pan_direction) {
131 int direction = 0; 118 Webcam::PanDirection direction = Webcam::PAN_STOP;
132 switch (params->config.pan_direction) { 119 switch (params->config.pan_direction) {
133 case webcam_private::PAN_DIRECTION_NONE: 120 case webcam_private::PAN_DIRECTION_NONE:
134 case webcam_private::PAN_DIRECTION_STOP: 121 case webcam_private::PAN_DIRECTION_STOP:
135 direction = 0; 122 direction = Webcam::PAN_STOP;
136 break; 123 break;
137 124
138 case webcam_private::PAN_DIRECTION_RIGHT: 125 case webcam_private::PAN_DIRECTION_RIGHT:
139 direction = 1; 126 direction = Webcam::PAN_RIGHT;
140 break; 127 break;
141 128
142 case webcam_private::PAN_DIRECTION_LEFT: 129 case webcam_private::PAN_DIRECTION_LEFT:
143 direction = -1; 130 direction = Webcam::PAN_LEFT;
144 break; 131 break;
145 } 132 }
146 SetWebcamParameter(fd.get(), V4L2_CID_PAN_SPEED, direction); 133 webcam->SetPanDirection(direction);
147 } 134 }
148 135
149 if (params->config.tilt) { 136 if (params->config.tilt) {
150 SetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE, 137 webcam->SetTilt(*(params->config.tilt));
151 *(params->config.tilt));
152 } 138 }
153 139
154 if (params->config.tilt_direction) { 140 if (params->config.tilt_direction) {
155 int direction = 0; 141 Webcam::TiltDirection direction = Webcam::TILT_STOP;
156 switch (params->config.tilt_direction) { 142 switch (params->config.tilt_direction) {
157 case webcam_private::TILT_DIRECTION_NONE: 143 case webcam_private::TILT_DIRECTION_NONE:
158 case webcam_private::TILT_DIRECTION_STOP: 144 case webcam_private::TILT_DIRECTION_STOP:
159 direction = 0; 145 direction = Webcam::TILT_STOP;
160 break; 146 break;
161 147
162 case webcam_private::TILT_DIRECTION_UP: 148 case webcam_private::TILT_DIRECTION_UP:
163 direction = 1; 149 direction = Webcam::TILT_UP;
164 break; 150 break;
165 151
166 case webcam_private::TILT_DIRECTION_DOWN: 152 case webcam_private::TILT_DIRECTION_DOWN:
167 direction = -1; 153 direction = Webcam::TILT_DOWN;
168 break; 154 break;
169 } 155 }
170 SetWebcamParameter(fd.get(), V4L2_CID_TILT_SPEED, direction); 156 webcam->SetTiltDirection(direction);
171 } 157 }
172 158
173 if (params->config.zoom) { 159 if (params->config.zoom) {
174 SetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, 160 webcam->SetZoom(*(params->config.zoom));
175 *(params->config.zoom));
176 } 161 }
177 162
178 163
179 return true; 164 return true;
180 } 165 }
181 166
182 WebcamPrivateGetFunction::WebcamPrivateGetFunction() { 167 WebcamPrivateGetFunction::WebcamPrivateGetFunction() {
183 } 168 }
184 169
185 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() { 170 WebcamPrivateGetFunction::~WebcamPrivateGetFunction() {
186 } 171 }
187 172
188 bool WebcamPrivateGetFunction::RunSync() { 173 bool WebcamPrivateGetFunction::RunSync() {
189 // Get parameters 174 // Get parameters
190 scoped_ptr<webcam_private::Get::Params> params( 175 scoped_ptr<webcam_private::Get::Params> params(
191 webcam_private::Get::Params::Create(*args_)); 176 webcam_private::Get::Params::Create(*args_));
192 EXTENSION_FUNCTION_VALIDATE(params.get()); 177 EXTENSION_FUNCTION_VALIDATE(params.get());
193 178
194 base::ScopedFD fd = 179 Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
195 OpenWebcam(extension_id(), browser_context(), params->webcam_id); 180 GetWebcam(extension_id(), params->webcam_id);
196 if (!fd.is_valid()) { 181 if (!webcam) {
197 SetError(kUnknownWebcam); 182 SetError(kUnknownWebcam);
198 return false; 183 return false;
199 } 184 }
200 185
201 webcam_private::WebcamConfiguration result; 186 webcam_private::WebcamConfiguration result;
202 187
203 int pan; 188 int pan;
204 if (GetWebcamParameter(fd.get(), V4L2_CID_PAN_ABSOLUTE, &pan)) 189 if (webcam->GetPan(&pan))
205 result.pan.reset(new double(pan)); 190 result.pan.reset(new double(pan));
206 191
207 int tilt; 192 int tilt;
208 if (GetWebcamParameter(fd.get(), V4L2_CID_TILT_ABSOLUTE, &tilt)) 193 if (webcam->GetTilt(&tilt))
209 result.tilt.reset(new double(tilt)); 194 result.tilt.reset(new double(tilt));
210 195
211 int zoom; 196 int zoom;
212 if (GetWebcamParameter(fd.get(), V4L2_CID_ZOOM_ABSOLUTE, &zoom)) 197 if (webcam->GetZoom(&zoom))
213 result.zoom.reset(new double(zoom)); 198 result.zoom.reset(new double(zoom));
214 199
215 SetResult(result.ToValue().release()); 200 SetResult(result.ToValue().release());
216 201
217 return true; 202 return true;
218 } 203 }
219 204
220 WebcamPrivateResetFunction::WebcamPrivateResetFunction() { 205 WebcamPrivateResetFunction::WebcamPrivateResetFunction() {
221 } 206 }
222 207
223 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() { 208 WebcamPrivateResetFunction::~WebcamPrivateResetFunction() {
224 } 209 }
225 210
226 bool WebcamPrivateResetFunction::RunSync() { 211 bool WebcamPrivateResetFunction::RunSync() {
227 // Get parameters 212 // Get parameters
228 scoped_ptr<webcam_private::Reset::Params> params( 213 scoped_ptr<webcam_private::Reset::Params> params(
229 webcam_private::Reset::Params::Create(*args_)); 214 webcam_private::Reset::Params::Create(*args_));
230 EXTENSION_FUNCTION_VALIDATE(params.get()); 215 EXTENSION_FUNCTION_VALIDATE(params.get());
231 216
232 base::ScopedFD fd = 217 Webcam* webcam = WebcamPrivateAPI::Get(browser_context())->
233 OpenWebcam(extension_id(), browser_context(), params->webcam_id); 218 GetWebcam(extension_id(), params->webcam_id);
234 if (!fd.is_valid()) { 219 if (!webcam) {
235 SetError(kUnknownWebcam); 220 SetError(kUnknownWebcam);
236 return false; 221 return false;
237 } 222 }
238 223
239 if (params->config.pan || params->config.tilt) { 224 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 225
261 return true; 226 return true;
262 } 227 }
263 228
229 static base::LazyInstance<BrowserContextKeyedAPIFactory<WebcamPrivateAPI>>
230 g_factory = LAZY_INSTANCE_INITIALIZER;
231
232 // static
233 BrowserContextKeyedAPIFactory<WebcamPrivateAPI>*
234 WebcamPrivateAPI::GetFactoryInstance() {
235 return g_factory.Pointer();
236 }
Ken Rockot(use gerrit already) 2015/05/14 00:07:02 You also need to declare your dependency on Proces
Zachary Kuznia 2015/05/14 17:25:11 Done.
237
264 } // namespace extensions 238 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/api/webcam_private/webcam_private_api.h ('k') | extensions/extensions.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698