OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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. | |
4 | |
5 #include "extensions/browser/api/media_perception_private/media_perception_api_m anager.h" | |
6 | |
7 #include "base/lazy_instance.h" | |
8 #include "base/memory/ptr_util.h" | |
9 #include "chromeos/dbus/dbus_thread_manager.h" | |
10 #include "chromeos/dbus/media_analytics_client.h" | |
11 #include "chromeos/dbus/upstart_client.h" | |
12 #include "extensions/browser/event_router.h" | |
13 #include "extensions/browser/extension_function.h" | |
14 | |
15 namespace media_perception = extensions::api::media_perception_private; | |
16 | |
17 namespace extensions { | |
18 | |
19 namespace { | |
20 | |
21 // p_result is owned by the caller. | |
22 void PointProtoToIdl(const mri::Point& point, | |
23 media_perception::Point* p_result) { | |
24 if (point.has_x()) { | |
25 p_result->x.reset(new double(point.x())); | |
26 } | |
27 if (point.has_y()) { | |
28 p_result->y.reset(new double(point.y())); | |
29 } | |
30 } | |
31 | |
32 // bbox_result is owned by the caller. | |
33 void BoundingBoxProtoToIdl(const mri::BoundingBox& bounding_box, | |
34 media_perception::BoundingBox* bbox_result) { | |
35 if (bounding_box.has_normalized()) { | |
36 bbox_result->normalized.reset(new bool(bounding_box.normalized())); | |
37 } | |
38 if (bounding_box.has_top_left()) { | |
39 bbox_result->top_left.reset(new media_perception::Point()); | |
40 PointProtoToIdl(bounding_box.top_left(), bbox_result->top_left.get()); | |
41 } | |
42 if (bounding_box.has_bottom_right()) { | |
43 bbox_result->bottom_right.reset(new media_perception::Point()); | |
44 PointProtoToIdl(bounding_box.bottom_right(), | |
45 bbox_result->bottom_right.get()); | |
46 } | |
47 } | |
48 | |
49 media_perception::Entity EntityProtoToIdl(const mri::Entity& entity) { | |
50 media_perception::Entity e_result; | |
51 if (entity.has_id()) { | |
52 e_result.id.reset(new int(entity.id())); | |
53 } | |
54 if (entity.has_type()) { | |
55 switch (entity.type()) { | |
56 case mri::Entity::FACE: | |
57 e_result.type = media_perception::ENTITY_TYPE_FACE; | |
58 break; | |
59 case mri::Entity::PERSON: | |
60 e_result.type = media_perception::ENTITY_TYPE_PERSON; | |
61 break; | |
62 default: | |
63 e_result.type = media_perception::ENTITY_TYPE_UNSPECIFIED; | |
64 } | |
65 } | |
66 if (entity.has_confidence()) { | |
67 e_result.confidence.reset(new double(entity.confidence())); | |
68 } | |
69 if (entity.has_bounding_box()) { | |
70 e_result.bounding_box.reset(new media_perception::BoundingBox()); | |
71 BoundingBoxProtoToIdl(entity.bounding_box(), e_result.bounding_box.get()); | |
72 } | |
73 return e_result; | |
74 } | |
75 | |
76 media_perception::FramePerception FramePerceptionProtoToIdl( | |
77 const mri::FramePerception& frame_perception) { | |
78 media_perception::FramePerception fp_result; | |
79 if (frame_perception.has_frame_id()) { | |
80 fp_result.frame_id.reset(new int(frame_perception.frame_id())); | |
81 } | |
82 if (frame_perception.has_frame_width_in_px()) { | |
83 fp_result.frame_width_in_px.reset( | |
84 new int(frame_perception.frame_width_in_px())); | |
85 } | |
86 if (frame_perception.has_frame_height_in_px()) { | |
87 fp_result.frame_height_in_px.reset( | |
88 new int(frame_perception.frame_height_in_px())); | |
89 } | |
90 if (frame_perception.has_timestamp()) { | |
91 fp_result.timestamp.reset(new double(frame_perception.timestamp())); | |
92 } | |
93 if (frame_perception.entity_size() > 0) { | |
94 fp_result.entities.reset(new std::vector<media_perception::Entity>()); | |
95 for (const auto& entity : frame_perception.entity()) { | |
96 fp_result.entities->emplace_back(EntityProtoToIdl(entity)); | |
97 } | |
98 } | |
99 return fp_result; | |
100 } | |
101 | |
102 media_perception::PerceptionSample PerceptionSampleProtoToIdl( | |
103 const mri::PerceptionSample& perception_sample) { | |
104 media_perception::PerceptionSample ps_result; | |
105 if (perception_sample.has_frame_perception()) { | |
106 ps_result.frame_perception.reset(new media_perception::FramePerception( | |
107 FramePerceptionProtoToIdl(perception_sample.frame_perception()))); | |
108 } | |
109 // TODO(lasoren): Implement ImageFrameProtoToIdl. | |
110 return ps_result; | |
111 } | |
112 | |
113 } // namespace | |
114 | |
115 media_perception::State StateProtoToIdl(const mri::State& state) { | |
116 media_perception::State s_result; | |
117 if (state.has_status()) { | |
118 switch (state.status()) { | |
119 case mri::State::UNINITIALIZED: | |
120 s_result.status = media_perception::STATUS_UNINITIALIZED; | |
121 break; | |
122 case mri::State::STARTED: | |
123 s_result.status = media_perception::STATUS_STARTED; | |
124 break; | |
125 case mri::State::RUNNING: | |
126 s_result.status = media_perception::STATUS_RUNNING; | |
127 break; | |
128 case mri::State::SUSPENDED: | |
129 s_result.status = media_perception::STATUS_SUSPENDED; | |
130 break; | |
131 default: | |
132 // Status unset. | |
133 break; | |
134 } | |
135 } | |
136 if (state.has_device_context()) { | |
137 s_result.device_context.reset(new std::string(state.device_context())); | |
138 } | |
139 return s_result; | |
140 } | |
141 | |
142 mri::State StateIdlToProto(const media_perception::State& state) { | |
143 mri::State s_result; | |
144 switch (state.status) { | |
145 case media_perception::STATUS_UNINITIALIZED: | |
146 s_result.set_status(mri::State::UNINITIALIZED); | |
147 break; | |
148 case media_perception::STATUS_STARTED: | |
149 s_result.set_status(mri::State::STARTED); | |
150 break; | |
151 case media_perception::STATUS_RUNNING: | |
152 s_result.set_status(mri::State::RUNNING); | |
153 break; | |
154 case media_perception::STATUS_SUSPENDED: | |
155 s_result.set_status(mri::State::SUSPENDED); | |
156 break; | |
157 default: | |
158 // Status unset. | |
159 break; | |
160 } | |
161 if (state.device_context) { | |
162 s_result.set_device_context(*state.device_context); | |
163 } | |
164 return s_result; | |
165 } | |
166 | |
167 media_perception::MediaPerception MediaPerceptionProtoToIdl( | |
168 const mri::MediaPerception& media_perception) { | |
169 media_perception::MediaPerception mp_result; | |
170 if (media_perception.has_timestamp()) { | |
171 mp_result.timestamp.reset(new double(media_perception.timestamp())); | |
172 } | |
173 if (media_perception.frame_perception_size() > 0) { | |
174 mp_result.frame_perceptions.reset( | |
175 new std::vector<media_perception::FramePerception>()); | |
176 for (const auto& frame_perception : media_perception.frame_perception()) { | |
177 mp_result.frame_perceptions->emplace_back( | |
178 FramePerceptionProtoToIdl(frame_perception)); | |
179 } | |
180 } | |
181 return mp_result; | |
182 } | |
183 | |
184 media_perception::Diagnostics DiagnosticsProtoToIdl( | |
185 const mri::Diagnostics& diagnostics) { | |
186 media_perception::Diagnostics d_result; | |
187 if (diagnostics.perception_sample_size() > 0) { | |
188 d_result.perception_samples.reset( | |
189 new std::vector<media_perception::PerceptionSample>()); | |
190 for (const auto& perception_sample : diagnostics.perception_sample()) { | |
191 d_result.perception_samples->emplace_back( | |
192 PerceptionSampleProtoToIdl(perception_sample)); | |
193 } | |
194 } | |
195 return d_result; | |
196 } | |
197 | |
198 // static | |
199 MediaPerceptionAPIManager* MediaPerceptionAPIManager::Get( | |
200 content::BrowserContext* context) { | |
201 return GetFactoryInstance()->Get(context); | |
202 } | |
203 | |
204 static base::LazyInstance< | |
205 BrowserContextKeyedAPIFactory<MediaPerceptionAPIManager>>::DestructorAtExit | |
206 g_factory = LAZY_INSTANCE_INITIALIZER; | |
207 | |
208 // static | |
209 BrowserContextKeyedAPIFactory<MediaPerceptionAPIManager>* | |
210 MediaPerceptionAPIManager::GetFactoryInstance() { | |
211 return g_factory.Pointer(); | |
212 } | |
213 | |
214 MediaPerceptionAPIManager::MediaPerceptionAPIManager( | |
215 content::BrowserContext* context) | |
216 : browser_context_(context), analytics_process_running_(false) { | |
217 chromeos::MediaAnalyticsClient* dbus_client = | |
218 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
219 dbus_client->SetMediaPerceptionSignalHandler( | |
220 base::Bind(&MediaPerceptionAPIManager::MediaPerceptionSignalHandler, | |
221 base::Unretained(this))); | |
222 } | |
223 | |
224 MediaPerceptionAPIManager::~MediaPerceptionAPIManager() { | |
225 chromeos::MediaAnalyticsClient* dbus_client = | |
226 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
227 dbus_client->UnsetMediaPerceptionSignalHandler(); | |
228 // TODO(lasoren): Verify this gets called at the right time. | |
229 // Stop the separate media analytics process. | |
230 chromeos::UpstartClient* upstart_client = | |
231 chromeos::DBusThreadManager::Get()->GetUpstartClient(); | |
232 upstart_client->StopMediaAnalytics(); | |
233 } | |
234 | |
235 void MediaPerceptionAPIManager::GetState(const APIStateCallback& callback) { | |
236 // Return uninitialized state if the media analytics process isn't running. | |
237 if (!analytics_process_running_) { | |
238 media_perception::State state_unitialized; | |
239 state_unitialized.status = media_perception::STATUS_UNINITIALIZED; | |
240 callback.Run(true, std::move(state_unitialized)); | |
241 return; | |
242 } | |
243 chromeos::MediaAnalyticsClient* dbus_client = | |
244 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
245 dbus_client->State(mri::State(), // Passing empty state changes nothing. | |
246 base::Bind(&MediaPerceptionAPIManager::StateCallback, | |
247 base::Unretained(this), callback)); | |
248 } | |
249 | |
250 void MediaPerceptionAPIManager::SetState(const media_perception::State& state, | |
251 const APIStateCallback& callback) { | |
252 mri::State state_proto = StateIdlToProto(state); | |
253 if (state_proto.status() != mri::State::RUNNING && | |
tbarzic
2017/05/05 21:10:41
can we do this check in the API function?
Luke Sorenson
2017/05/08 19:06:06
Done. In https://codereview.chromium.org/285835300
| |
254 state_proto.status() != mri::State::SUSPENDED) { | |
255 LOG(ERROR) << "Cannot set state to something other than RUNNING or " | |
256 "SUSPENDED."; | |
257 media_perception::State empty_state; | |
258 callback.Run(false, std::move(empty_state)); | |
259 return; | |
260 } | |
261 if (!analytics_process_running_) { | |
262 if (state_proto.status() == mri::State::RUNNING) { | |
263 chromeos::UpstartClient* dbus_client = | |
264 chromeos::DBusThreadManager::Get()->GetUpstartClient(); | |
265 dbus_client->StartMediaAnalytics( | |
266 base::Bind(&MediaPerceptionAPIManager::UpstartCallback, | |
267 base::Unretained(this), callback, state_proto)); | |
268 } else { | |
269 media_perception::State empty_state; | |
270 callback.Run(false, std::move(empty_state)); | |
271 } | |
272 } else { | |
273 SetStateInternal(callback, state_proto); | |
274 } | |
275 } | |
276 | |
277 void MediaPerceptionAPIManager::SetStateInternal( | |
278 const APIStateCallback& callback, | |
279 const mri::State& state) { | |
280 chromeos::MediaAnalyticsClient* dbus_client = | |
281 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
282 dbus_client->State(state, | |
283 base::Bind(&MediaPerceptionAPIManager::StateCallback, | |
284 base::Unretained(this), callback)); | |
285 } | |
286 | |
287 void MediaPerceptionAPIManager::GetDiagnostics( | |
288 const APIGetDiagnosticsCallback& callback) { | |
289 chromeos::MediaAnalyticsClient* dbus_client = | |
290 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient(); | |
291 dbus_client->GetDiagnostics( | |
292 base::Bind(&MediaPerceptionAPIManager::GetDiagnosticsCallback, | |
293 base::Unretained(this), callback)); | |
294 } | |
295 | |
296 void MediaPerceptionAPIManager::UpstartCallback( | |
297 const APIStateCallback& callback, | |
298 const mri::State& state, | |
299 bool succeeded) { | |
300 if (succeeded) { | |
301 analytics_process_running_ = true; | |
302 SetStateInternal(callback, state); | |
303 } else { | |
304 analytics_process_running_ = false; | |
305 LOG(ERROR) << "Failed to start media analytics process via Upstart."; | |
306 media_perception::State empty_state; | |
307 callback.Run(false, std::move(empty_state)); | |
308 } | |
309 } | |
310 | |
311 void MediaPerceptionAPIManager::StateCallback(const APIStateCallback& callback, | |
312 bool succeeded, | |
313 const mri::State& state_proto) { | |
314 media_perception::State state; | |
315 if (!succeeded) { | |
316 state.status = media_perception::STATUS_TIMEOUT; | |
317 callback.Run(false, std::move(state)); | |
318 return; | |
319 } | |
320 state = StateProtoToIdl(state_proto); | |
321 callback.Run(true, std::move(state)); | |
322 } | |
323 | |
324 void MediaPerceptionAPIManager::GetDiagnosticsCallback( | |
325 const APIGetDiagnosticsCallback& callback, | |
326 bool succeeded, | |
327 const mri::Diagnostics& diagnostics_proto) { | |
328 media_perception::Diagnostics diagnostics; | |
329 if (!succeeded) { | |
330 callback.Run(false, std::move(diagnostics)); | |
331 return; | |
332 } | |
333 diagnostics = DiagnosticsProtoToIdl(diagnostics_proto); | |
334 callback.Run(true, std::move(diagnostics)); | |
335 } | |
336 | |
337 void MediaPerceptionAPIManager::MediaPerceptionSignalHandler( | |
338 const mri::MediaPerception& media_perception_proto) { | |
339 EventRouter* router = EventRouter::Get(browser_context_); | |
340 if (!router || !router->HasEventListener( | |
341 media_perception::OnMediaPerception::kEventName)) { | |
342 return; | |
343 } | |
344 media_perception::MediaPerception media_perception = | |
345 MediaPerceptionProtoToIdl(media_perception_proto); | |
346 std::unique_ptr<Event> event( | |
347 new Event(events::MEDIA_PERCEPTION_PRIVATE_ON_MEDIA_PERCEPTION, | |
348 media_perception::OnMediaPerception::kEventName, | |
349 media_perception::OnMediaPerception::Create(media_perception))); | |
350 router->BroadcastEvent(std::move(event)); | |
351 } | |
352 | |
353 } // namespace extensions | |
OLD | NEW |