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

Side by Side Diff: extensions/browser/api/media_perception_private/media_perception_api_manager.cc

Issue 2791983004: DBus MediaAnalyticsClient and media_perception pb. (Closed)
Patch Set: Upstart process management Created 3 years, 8 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
(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 "extensions/browser/event_router.h"
12 #include "extensions/browser/extension_function.h"
13
14 namespace mpp = extensions::api::media_perception_private;
tbarzic 2017/04/27 20:37:36 can you use more meaningful name here?
Luke Sorenson 2017/05/03 23:56:07 Done.
15
16 namespace extensions {
17
18 namespace {
19
20 // p_result is owned by the caller.
21 void PointProtoToIdl(const mri::Point& point, mpp::Point* p_result) {
22 if (point.has_x()) {
23 p_result->x.reset(new double(point.x()));
24 }
25 if (point.has_y()) {
26 p_result->y.reset(new double(point.y()));
27 }
28 }
29
30 // bbox_result is owned by the caller.
31 void BoundingBoxProtoToIdl(const mri::BoundingBox& bounding_box,
32 mpp::BoundingBox* bbox_result) {
33 if (bounding_box.has_normalized()) {
34 bbox_result->normalized.reset(new bool(bounding_box.normalized()));
35 }
36 if (bounding_box.has_top_left()) {
37 bbox_result->top_left.reset(new mpp::Point());
tbarzic 2017/04/27 20:37:36 suiggestion: use base::MakeUnique to create unique
Luke Sorenson 2017/05/03 23:56:07 In this case, the unique_ptrs already exist, becau
tbarzic 2017/05/05 21:10:40 yes, this works, but I think bbox_result->top_lef
Luke Sorenson 2017/05/08 19:06:06 Seems strange to waste CPU (even if it is fairly n
tbarzic 2017/05/08 23:04:55 I don't think there's a particular syle guide for
rkc1 2017/05/08 23:34:09 Look at the comment above base::MakeUnique. It spe
Luke Sorenson 2017/05/09 17:39:45 Done. Changes made in https://codereview.chromium.
38 PointProtoToIdl(bounding_box.top_left(), bbox_result->top_left.get());
39 }
40 if (bounding_box.has_bottom_right()) {
41 bbox_result->bottom_right.reset(new mpp::Point());
42 PointProtoToIdl(bounding_box.bottom_right(),
43 bbox_result->bottom_right.get());
44 }
45 }
46
47 mpp::Entity EntityProtoToIdl(const mri::Entity& entity) {
48 mpp::Entity e_result;
49 if (entity.has_id()) {
50 e_result.id.reset(new int(entity.id()));
51 }
52 if (entity.has_type()) {
53 switch (entity.type()) {
54 case mri::Entity::FACE:
55 e_result.type = mpp::ENTITY_TYPE_FACE;
56 break;
57 case mri::Entity::PERSON:
58 e_result.type = mpp::ENTITY_TYPE_PERSON;
59 break;
60 default:
61 e_result.type = mpp::ENTITY_TYPE_UNSPECIFIED;
62 }
63 }
64 if (entity.has_confidence()) {
65 e_result.confidence.reset(new double(entity.confidence()));
66 }
67 if (entity.has_bounding_box()) {
68 e_result.bounding_box.reset(new mpp::BoundingBox());
69 BoundingBoxProtoToIdl(entity.bounding_box(), e_result.bounding_box.get());
70 }
71 return e_result;
72 }
73
74 mpp::FramePerception FramePerceptionProtoToIdl(
75 const mri::FramePerception& frame_perception) {
76 mpp::FramePerception fp_result;
77 if (frame_perception.has_frame_id()) {
78 fp_result.frame_id.reset(new int(frame_perception.frame_id()));
79 }
80 if (frame_perception.has_frame_width_in_px()) {
81 fp_result.frame_width_in_px.reset(
82 new int(frame_perception.frame_width_in_px()));
83 }
84 if (frame_perception.has_frame_height_in_px()) {
85 fp_result.frame_height_in_px.reset(
86 new int(frame_perception.frame_height_in_px()));
87 }
88 if (frame_perception.has_timestamp()) {
89 fp_result.timestamp.reset(new double(frame_perception.timestamp()));
90 }
91 if (frame_perception.entity_size() > 0) {
92 fp_result.entities.reset(new std::vector<mpp::Entity>());
93 for (const auto& entity : frame_perception.entity()) {
94 fp_result.entities->emplace_back(EntityProtoToIdl(entity));
95 }
96 }
97 return fp_result;
98 }
99
100 mpp::PerceptionSample PerceptionSampleProtoToIdl(
101 const mri::PerceptionSample& perception_sample) {
102 mpp::PerceptionSample ps_result;
103 if (perception_sample.has_frame_perception()) {
104 ps_result.frame_perception.reset(new mpp::FramePerception(
105 FramePerceptionProtoToIdl(perception_sample.frame_perception())));
106 }
107 // TODO(lasoren): Implement ImageFrameProtoToIdl.
108 return ps_result;
109 }
110
111 } // namespace
112
113 mpp::State StateProtoToIdl(const mri::State& state) {
114 mpp::State s_result;
115 if (state.has_status()) {
116 switch (state.status()) {
117 case mri::State::UNINITIALIZED:
118 s_result.status = mpp::STATUS_UNINITIALIZED;
119 break;
120 case mri::State::STARTED:
121 s_result.status = mpp::STATUS_STARTED;
122 break;
123 case mri::State::RUNNING:
124 s_result.status = mpp::STATUS_RUNNING;
125 break;
126 case mri::State::SUSPENDED:
127 s_result.status = mpp::STATUS_SUSPENDED;
128 break;
129 default:
130 // Status unset.
131 break;
132 }
133 }
134 if (state.has_device_context()) {
135 s_result.device_context.reset(new std::string(state.device_context()));
136 }
137 return s_result;
138 }
139
140 mri::State StateIdlToProto(const mpp::State& state) {
141 mri::State s_result;
142 switch (state.status) {
143 case mpp::STATUS_UNINITIALIZED:
144 s_result.set_status(mri::State::UNINITIALIZED);
145 break;
146 case mpp::STATUS_STARTED:
147 s_result.set_status(mri::State::STARTED);
148 break;
149 case mpp::STATUS_RUNNING:
150 s_result.set_status(mri::State::RUNNING);
151 break;
152 case mpp::STATUS_SUSPENDED:
153 s_result.set_status(mri::State::SUSPENDED);
154 break;
155 default:
156 // Status unset.
157 break;
158 }
159 if (state.device_context) {
160 s_result.set_device_context(*state.device_context);
161 }
162 return s_result;
163 }
164
165 mpp::MediaPerception MediaPerceptionProtoToIdl(
166 const mri::MediaPerception& media_perception) {
167 mpp::MediaPerception mpp_result;
168 if (media_perception.has_timestamp()) {
169 mpp_result.timestamp.reset(new double(media_perception.timestamp()));
170 }
171 if (media_perception.frame_perception_size() > 0) {
172 mpp_result.frame_perceptions.reset(new std::vector<mpp::FramePerception>());
173 for (const auto& frame_perception : media_perception.frame_perception()) {
174 mpp_result.frame_perceptions->emplace_back(
175 FramePerceptionProtoToIdl(frame_perception));
176 }
177 }
178 return mpp_result;
179 }
180
181 mpp::Diagnostics DiagnosticsProtoToIdl(const mri::Diagnostics& diagnostics) {
182 mpp::Diagnostics d_result;
183 if (diagnostics.perception_sample_size() > 0) {
184 d_result.perception_samples.reset(new std::vector<mpp::PerceptionSample>());
185 for (const auto& perception_sample : diagnostics.perception_sample()) {
186 d_result.perception_samples->emplace_back(
187 PerceptionSampleProtoToIdl(perception_sample));
188 }
189 }
190 return d_result;
191 }
192
193 // static
194 MediaPerceptionAPIManager* MediaPerceptionAPIManager::Get(
195 content::BrowserContext* context) {
196 return GetFactoryInstance()->Get(context);
197 }
198
199 static base::LazyInstance<
200 BrowserContextKeyedAPIFactory<MediaPerceptionAPIManager>>::DestructorAtExit
201 g_factory = LAZY_INSTANCE_INITIALIZER;
202
203 // static
204 BrowserContextKeyedAPIFactory<MediaPerceptionAPIManager>*
205 MediaPerceptionAPIManager::GetFactoryInstance() {
206 return g_factory.Pointer();
207 }
208
209 MediaPerceptionAPIManager::MediaPerceptionAPIManager(
210 content::BrowserContext* context)
211 : browser_context_(context), analytics_process_running_(false) {}
212
213 MediaPerceptionAPIManager::~MediaPerceptionAPIManager() {}
214
215 void MediaPerceptionAPIManager::GetState(const APIStateCallback& callback) {
216 chromeos::MediaAnalyticsClient* dbus_client =
217 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient();
218 api_state_callback_ = callback;
tbarzic 2017/04/27 20:37:36 This won't work if there is another request before
Luke Sorenson 2017/05/03 23:56:07 Done.
219 dbus_client->State(nullptr, 0,
220 base::Bind(&MediaPerceptionAPIManager::StateCallback,
221 base::Unretained(this)));
222 }
223
224 void MediaPerceptionAPIManager::SetState(const mpp::State& state,
225 const APIStateCallback& callback) {
226 desired_state_ = StateIdlToProto(state);
227 api_state_callback_ = callback;
228
229 if (!analytics_process_running_) {
230 chromeos::MediaAnalyticsClient* dbus_client =
231 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient();
232 dbus_client->StartMediaAnalytics(base::Bind(
tbarzic 2017/04/27 20:37:36 doing this if state is anything else than STARTED
Luke Sorenson 2017/05/03 23:56:07 Done. Although in this case it would be for SetSta
233 &MediaPerceptionAPIManager::UpstartCallback, base::Unretained(this)));
234 } else {
235 SetStateInternal();
236 }
237 }
238
239 void MediaPerceptionAPIManager::SetStateInternal() {
240 chromeos::MediaAnalyticsClient* dbus_client =
241 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient();
242 int size = desired_state_.ByteSize();
243 uint8_t buffer[size];
244 desired_state_.SerializeToArray(buffer, size);
245 dbus_client->State(buffer, size,
246 base::Bind(&MediaPerceptionAPIManager::StateCallback,
247 base::Unretained(this)));
248 }
249
250 void MediaPerceptionAPIManager::GetDiagnostics(
251 const APIGetDiagnosticsCallback& callback) {
252 chromeos::MediaAnalyticsClient* dbus_client =
253 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient();
254 api_get_diagnostics_callback_ = callback;
255 dbus_client->GetDiagnostics(
256 base::Bind(&MediaPerceptionAPIManager::GetDiagnosticsCallback,
257 base::Unretained(this)));
258 }
259
260 void MediaPerceptionAPIManager::UpstartCallback(bool succeeded) {
261 if (succeeded) {
262 analytics_process_running_ = true;
263 SetStateInternal();
264 } else {
265 analytics_process_running_ = false;
266 LOG(ERROR) << "Failed to start media analytics process via Upstart.";
267 // TODO(lasoren): Consider propagating error up to the frontend.
tbarzic 2017/04/27 20:37:36 you should invoke the API callback so the referenc
Luke Sorenson 2017/05/03 23:56:07 Done.
268 }
269 }
270
271 void MediaPerceptionAPIManager::StateCallback(bool succeeded,
272 const uint8_t* bytes,
273 size_t length) {
274 mpp::State state;
275 if (!succeeded) {
276 state.status = mpp::STATUS_TIMEOUT;
277 api_state_callback_.Run(false, std::move(state));
278 return;
279 }
280 mri::State state_proto;
281 if (!state_proto.ParseFromArray(bytes, length)) {
282 LOG(ERROR) << "Failed to parse State message.";
283 api_state_callback_.Run(false, std::move(state));
284 return;
285 }
286 // If the media analytics process is started, register an event handler to get
287 // detections on the frontend.
288 if (state_proto.status() == mri::State::STARTED) {
tbarzic 2017/04/27 20:37:35 This seems a little too magical :/ Does this mean
Luke Sorenson 2017/05/03 23:56:07 The app wouldn't need to poll until it gets STARTE
289 chromeos::MediaAnalyticsClient* dbus_client =
290 chromeos::DBusThreadManager::Get()->GetMediaAnalyticsClient();
291 dbus_client->SetMediaPerceptionSignalHandler(
292 base::Bind(&MediaPerceptionAPIManager::MediaPerceptionSignalHandler,
293 base::Unretained(this)));
tbarzic 2017/04/27 20:37:36 Can we use weak ptr here instead of unretained.
Luke Sorenson 2017/05/03 23:56:07 Handler unset when the class is destructed. What
294 }
295 state = StateProtoToIdl(state_proto);
296 api_state_callback_.Run(true, std::move(state));
297 }
298
299 void MediaPerceptionAPIManager::GetDiagnosticsCallback(bool succeeded,
300 const uint8_t* bytes,
301 size_t length) {
302 mpp::Diagnostics diagnostics;
303 if (!succeeded) {
304 api_get_diagnostics_callback_.Run(false, std::move(diagnostics));
tbarzic 2017/04/27 20:37:35 can we pass in the callback as GetDiagnosticsCallb
Luke Sorenson 2017/05/03 23:56:07 Done.
305 return;
306 }
307 mri::Diagnostics diagnostics_proto;
308 if (!diagnostics_proto.ParseFromArray(bytes, length)) {
tbarzic 2017/04/27 20:37:36 I wonder if proto parsing should be done by dbus c
Luke Sorenson 2017/05/03 23:56:07 In my prior implementation the media_perception.pr
309 LOG(ERROR) << "Failed to parse State message.";
310 api_get_diagnostics_callback_.Run(false, std::move(diagnostics));
311 return;
312 }
313 diagnostics = DiagnosticsProtoToIdl(diagnostics_proto);
314 api_get_diagnostics_callback_.Run(true, std::move(diagnostics));
315 }
316
317 void MediaPerceptionAPIManager::MediaPerceptionSignalHandler(
318 const uint8_t* bytes,
319 size_t length) {
320 EventRouter* router = EventRouter::Get(browser_context_);
321 if (router && router->HasEventListener(mpp::OnMediaPerception::kEventName)) {
tbarzic 2017/04/27 20:37:36 if (!router || !router->HasEventListener(...)) r
Luke Sorenson 2017/05/03 23:56:07 Done.
322 mri::MediaPerception media_perception;
323 if (!media_perception.ParseFromArray(bytes, length)) {
324 LOG(ERROR) << "Failed to parse MediaPerception message.";
325 return;
326 }
327 mpp::MediaPerception mp_result =
328 MediaPerceptionProtoToIdl(media_perception);
329 std::unique_ptr<Event> event(
330 new Event(events::MEDIA_PERCEPTION_PRIVATE_ON_MEDIA_PERCEPTION,
331 mpp::OnMediaPerception::kEventName,
332 mpp::OnMediaPerception::Create(mp_result)));
333 router->BroadcastEvent(std::move(event));
334 }
335 }
336
337 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698