1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "session_coordinator.h"
17
18 #include "dp_log.h"
19 #include "buffer_info.h"
20 #include "dps_event_report.h"
21 #include "steady_clock.h"
22 #include "picture.h"
23 #include "video_session_info.h"
24
25 namespace OHOS {
26 namespace CameraStandard {
27 namespace DeferredProcessing {
MapDpsErrorCode(DpsError errorCode)28 ErrorCode MapDpsErrorCode(DpsError errorCode)
29 {
30 ErrorCode code = ErrorCode::ERROR_IMAGE_PROC_ABNORMAL;
31 switch (errorCode) {
32 case DpsError::DPS_ERROR_SESSION_SYNC_NEEDED:
33 code = ErrorCode::ERROR_SESSION_SYNC_NEEDED;
34 break;
35 case DpsError::DPS_ERROR_SESSION_NOT_READY_TEMPORARILY:
36 code = ErrorCode::ERROR_SESSION_NOT_READY_TEMPORARILY;
37 break;
38 case DpsError::DPS_ERROR_IMAGE_PROC_INVALID_PHOTO_ID:
39 code = ErrorCode::ERROR_IMAGE_PROC_INVALID_PHOTO_ID;
40 break;
41 case DpsError::DPS_ERROR_IMAGE_PROC_FAILED:
42 code = ErrorCode::ERROR_IMAGE_PROC_FAILED;
43 break;
44 case DpsError::DPS_ERROR_IMAGE_PROC_TIMEOUT:
45 code = ErrorCode::ERROR_IMAGE_PROC_TIMEOUT;
46 break;
47 case DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL:
48 code = ErrorCode::ERROR_IMAGE_PROC_ABNORMAL;
49 break;
50 case DpsError::DPS_ERROR_IMAGE_PROC_INTERRUPTED:
51 code = ErrorCode::ERROR_IMAGE_PROC_INTERRUPTED;
52 break;
53 case DpsError::DPS_ERROR_VIDEO_PROC_INVALID_VIDEO_ID:
54 code = ErrorCode::ERROR_VIDEO_PROC_INVALID_VIDEO_ID;
55 break;
56 case DpsError::DPS_ERROR_VIDEO_PROC_FAILED:
57 code = ErrorCode::ERROR_VIDEO_PROC_FAILED;
58 break;
59 case DpsError::DPS_ERROR_VIDEO_PROC_TIMEOUT:
60 code = ErrorCode::ERROR_VIDEO_PROC_TIMEOUT;
61 break;
62 case DpsError::DPS_ERROR_VIDEO_PROC_INTERRUPTED:
63 code = ErrorCode::ERROR_VIDEO_PROC_INTERRUPTED;
64 break;
65 default:
66 DP_WARNING_LOG("unexpected error code: %{public}d.", errorCode);
67 break;
68 }
69 return code;
70 }
71
MapDpsStatus(DpsStatus statusCode)72 StatusCode MapDpsStatus(DpsStatus statusCode)
73 {
74 StatusCode code = StatusCode::SESSION_STATE_IDLE;
75 switch (statusCode) {
76 case DpsStatus::DPS_SESSION_STATE_IDLE:
77 code = StatusCode::SESSION_STATE_IDLE;
78 break;
79 case DpsStatus::DPS_SESSION_STATE_RUNNALBE:
80 code = StatusCode::SESSION_STATE_RUNNALBE;
81 break;
82 case DpsStatus::DPS_SESSION_STATE_RUNNING:
83 code = StatusCode::SESSION_STATE_RUNNING;
84 break;
85 case DpsStatus::DPS_SESSION_STATE_SUSPENDED:
86 code = StatusCode::SESSION_STATE_SUSPENDED;
87 break;
88 default:
89 DP_WARNING_LOG("unexpected error code: %{public}d.", statusCode);
90 break;
91 }
92 return code;
93 }
94
95 class SessionCoordinator::ImageProcCallbacks : public IImageProcessCallbacks {
96 public:
ImageProcCallbacks(SessionCoordinator * coordinator)97 explicit ImageProcCallbacks(SessionCoordinator* coordinator) : coordinator_(coordinator)
98 {
99 }
100
~ImageProcCallbacks()101 ~ImageProcCallbacks() override
102 {
103 coordinator_ = nullptr;
104 }
105
OnProcessDone(const int32_t userId,const std::string & imageId,std::shared_ptr<BufferInfo> bufferInfo)106 void OnProcessDone(const int32_t userId, const std::string& imageId,
107 std::shared_ptr<BufferInfo> bufferInfo) override
108 {
109 sptr<IPCFileDescriptor> ipcFd = bufferInfo->GetIPCFileDescriptor();
110 int32_t dataSize = bufferInfo->GetDataSize();
111 bool isCloudImageEnhanceSupported = bufferInfo->IsCloudImageEnhanceSupported();
112 if (coordinator_) {
113 coordinator_->OnProcessDone(userId, imageId, ipcFd, dataSize, isCloudImageEnhanceSupported);
114 }
115 }
116
OnProcessDoneExt(int userId,const std::string & imageId,std::shared_ptr<BufferInfoExt> bufferInfo)117 void OnProcessDoneExt(int userId, const std::string& imageId,
118 std::shared_ptr<BufferInfoExt> bufferInfo) override
119 {
120 bool isCloudImageEnhanceSupported = bufferInfo->IsCloudImageEnhanceSupported();
121 if (coordinator_ && bufferInfo) {
122 coordinator_->OnProcessDoneExt(userId, imageId, bufferInfo->GetPicture(), isCloudImageEnhanceSupported);
123 }
124 }
125
OnError(const int userId,const std::string & imageId,DpsError errorCode)126 void OnError(const int userId, const std::string& imageId, DpsError errorCode) override
127 {
128 DP_CHECK_EXECUTE(coordinator_ != nullptr, coordinator_->OnError(userId, imageId, errorCode));
129 }
130
OnStateChanged(const int32_t userId,DpsStatus statusCode)131 void OnStateChanged(const int32_t userId, DpsStatus statusCode) override
132 {
133 DP_CHECK_EXECUTE(coordinator_ != nullptr, coordinator_->OnStateChanged(userId, statusCode));
134 }
135
136 private:
137 SessionCoordinator* coordinator_;
138 };
139
140 class SessionCoordinator::VideoProcCallbacks : public IVideoProcessCallbacks {
141 public:
VideoProcCallbacks(const std::weak_ptr<SessionCoordinator> & coordinator)142 explicit VideoProcCallbacks(const std::weak_ptr<SessionCoordinator>& coordinator) : coordinator_(coordinator)
143 {
144 }
145
146 ~VideoProcCallbacks() = default;
147
OnProcessDone(const int32_t userId,const std::string & videoId,const sptr<IPCFileDescriptor> & ipcFd)148 void OnProcessDone(const int32_t userId, const std::string& videoId,
149 const sptr<IPCFileDescriptor>& ipcFd) override
150 {
151 auto video = coordinator_.lock();
152 DP_CHECK_ERROR_RETURN_LOG(video == nullptr, "SessionCoordinator is nullptr.");
153 video->OnVideoProcessDone(userId, videoId, ipcFd);
154 }
155
OnError(const int32_t userId,const std::string & videoId,DpsError errorCode)156 void OnError(const int32_t userId, const std::string& videoId, DpsError errorCode) override
157 {
158 auto video = coordinator_.lock();
159 DP_CHECK_ERROR_RETURN_LOG(video == nullptr, "SessionCoordinator is nullptr.");
160 video->OnVideoError(userId, videoId, errorCode);
161 }
162
OnStateChanged(const int32_t userId,DpsStatus statusCode)163 void OnStateChanged(const int32_t userId, DpsStatus statusCode) override
164 {
165 auto video = coordinator_.lock();
166 DP_CHECK_ERROR_RETURN_LOG(video == nullptr, "SessionCoordinator is nullptr.");
167 video->OnStateChanged(userId, statusCode);
168 }
169
170 private:
171 std::weak_ptr<SessionCoordinator> coordinator_;
172 };
173
SessionCoordinator()174 SessionCoordinator::SessionCoordinator()
175 : imageProcCallbacks_(nullptr),
176 remoteImageCallbacksMap_(),
177 pendingImageResults_(),
178 videoProcCallbacks_(nullptr),
179 remoteVideoCallbacksMap_(),
180 pendingRequestResults_()
181 {
182 DP_DEBUG_LOG("entered.");
183 }
184
~SessionCoordinator()185 SessionCoordinator::~SessionCoordinator()
186 {
187 DP_DEBUG_LOG("entered.");
188 imageProcCallbacks_ = nullptr;
189 remoteImageCallbacksMap_.clear();
190 pendingImageResults_.clear();
191 videoProcCallbacks_ = nullptr;
192 remoteVideoCallbacksMap_.clear();
193 pendingRequestResults_.clear();
194 }
195
Initialize()196 void SessionCoordinator::Initialize()
197 {
198 imageProcCallbacks_ = std::make_shared<ImageProcCallbacks>(this);
199 videoProcCallbacks_ = std::make_shared<VideoProcCallbacks>(weak_from_this());
200 }
201
Start()202 void SessionCoordinator::Start()
203 {
204 //dps_log
205 }
206
Stop()207 void SessionCoordinator::Stop()
208 {
209 //dps_log
210 }
211
GetImageProcCallbacks()212 std::shared_ptr<IImageProcessCallbacks> SessionCoordinator::GetImageProcCallbacks()
213 {
214 return imageProcCallbacks_;
215 }
216
GetVideoProcCallbacks()217 std::shared_ptr<IVideoProcessCallbacks> SessionCoordinator::GetVideoProcCallbacks()
218 {
219 return videoProcCallbacks_;
220 }
221
OnProcessDone(const int32_t userId,const std::string & imageId,const sptr<IPCFileDescriptor> & ipcFd,const int32_t dataSize,bool isCloudImageEnhanceSupported)222 void SessionCoordinator::OnProcessDone(const int32_t userId, const std::string& imageId,
223 const sptr<IPCFileDescriptor>& ipcFd, const int32_t dataSize, bool isCloudImageEnhanceSupported)
224 {
225 DP_INFO_LOG("entered, userId: %{public}d, map size: %{public}d.",
226 userId, static_cast<int32_t>(remoteImageCallbacksMap_.size()));
227 auto iter = remoteImageCallbacksMap_.find(userId);
228 if (iter != remoteImageCallbacksMap_.end()) {
229 auto wpCallback = iter->second;
230 sptr<IDeferredPhotoProcessingSessionCallback> spCallback = wpCallback.promote();
231 DP_INFO_LOG("entered, imageId: %{public}s", imageId.c_str());
232 spCallback->OnProcessImageDone(imageId, ipcFd, dataSize, isCloudImageEnhanceSupported);
233 } else {
234 DP_INFO_LOG("callback is null, cache request, imageId: %{public}s.", imageId.c_str());
235 pendingImageResults_.push_back({CallbackType::ON_PROCESS_DONE, userId, imageId, ipcFd, dataSize,
236 DpsError::DPS_ERROR_SESSION_SYNC_NEEDED, DpsStatus::DPS_SESSION_STATE_IDLE,
237 isCloudImageEnhanceSupported});
238 }
239 return;
240 }
241
OnProcessDoneExt(int userId,const std::string & imageId,std::shared_ptr<Media::Picture> picture,bool isCloudImageEnhanceSupported)242 void SessionCoordinator::OnProcessDoneExt(int userId, const std::string& imageId,
243 std::shared_ptr<Media::Picture> picture, bool isCloudImageEnhanceSupported)
244 {
245 auto iter = remoteImageCallbacksMap_.find(userId);
246 if (iter != remoteImageCallbacksMap_.end()) {
247 auto wpCallback = iter->second;
248 sptr<IDeferredPhotoProcessingSessionCallback> spCallback = wpCallback.promote();
249 DP_INFO_LOG("entered, imageId: %s", imageId.c_str());
250 spCallback->OnProcessImageDone(imageId, picture, isCloudImageEnhanceSupported);
251 } else {
252 DP_INFO_LOG("callback is null, cache request, imageId: %{public}s.", imageId.c_str());
253 }
254 return;
255 }
256
OnError(const int userId,const std::string & imageId,DpsError errorCode)257 void SessionCoordinator::OnError(const int userId, const std::string& imageId, DpsError errorCode)
258 {
259 auto iter = remoteImageCallbacksMap_.find(userId);
260 if (iter != remoteImageCallbacksMap_.end()) {
261 auto wpCallback = iter->second;
262 sptr<IDeferredPhotoProcessingSessionCallback> spCallback = wpCallback.promote();
263 DP_INFO_LOG("entered, userId: %{public}d", userId);
264 spCallback->OnError(imageId, MapDpsErrorCode(errorCode));
265 } else {
266 DP_INFO_LOG("callback is null, cache request, imageId: %{public}s, errorCode: %{public}d.",
267 imageId.c_str(), errorCode);
268 pendingImageResults_.push_back({CallbackType::ON_ERROR, userId, imageId, nullptr, 0, errorCode});
269 }
270 }
271
OnStateChanged(const int32_t userId,DpsStatus statusCode)272 void SessionCoordinator::OnStateChanged(const int32_t userId, DpsStatus statusCode)
273 {
274 auto iter = remoteImageCallbacksMap_.find(userId);
275 if (iter != remoteImageCallbacksMap_.end()) {
276 auto wpCallback = iter->second;
277 sptr<IDeferredPhotoProcessingSessionCallback> spCallback = wpCallback.promote();
278 DP_INFO_LOG("entered, userId: %{public}d", userId);
279 spCallback->OnStateChanged(MapDpsStatus(statusCode));
280 } else {
281 DP_INFO_LOG("cache request, statusCode: %{public}d.", statusCode);
282 pendingImageResults_.push_back({CallbackType::ON_STATE_CHANGED, userId, "", nullptr, 0,
283 DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL, statusCode});
284 }
285 }
286
NotifySessionCreated(const int32_t userId,sptr<IDeferredPhotoProcessingSessionCallback> callback,TaskManager * taskManager)287 void SessionCoordinator::NotifySessionCreated(const int32_t userId,
288 sptr<IDeferredPhotoProcessingSessionCallback> callback, TaskManager* taskManager)
289 {
290 if (callback) {
291 remoteImageCallbacksMap_[userId] = callback;
292 taskManager->SubmitTask([this, callback]() {
293 this->ProcessPendingResults(callback);
294 });
295 }
296 }
297
ProcessPendingResults(sptr<IDeferredPhotoProcessingSessionCallback> callback)298 void SessionCoordinator::ProcessPendingResults(sptr<IDeferredPhotoProcessingSessionCallback> callback)
299 {
300 DP_INFO_LOG("entered.");
301 while (!pendingImageResults_.empty()) {
302 auto result = pendingImageResults_.front();
303 if (result.callbackType == CallbackType::ON_PROCESS_DONE) {
304 callback->OnProcessImageDone(result.imageId, result.ipcFd, result.dataSize,
305 result.isCloudImageEnhanceSupported);
306 uint64_t endTime = SteadyClock::GetTimestampMilli();
307 DPSEventReport::GetInstance().ReportImageProcessResult(result.imageId, result.userId, endTime);
308 }
309 if (result.callbackType == CallbackType::ON_ERROR) {
310 callback->OnError(result.imageId, MapDpsErrorCode(result.errorCode));
311 }
312 if (result.callbackType == CallbackType::ON_STATE_CHANGED) {
313 callback->OnStateChanged(MapDpsStatus(result.statusCode));
314 }
315 pendingImageResults_.pop_front();
316 }
317 }
318
NotifyCallbackDestroyed(const int32_t userId)319 void SessionCoordinator::NotifyCallbackDestroyed(const int32_t userId)
320 {
321 if (remoteImageCallbacksMap_.count(userId) != 0) {
322 DP_INFO_LOG("session userId: %{public}d destroyed.", userId);
323 remoteImageCallbacksMap_.erase(userId);
324 }
325 }
326
AddSession(const sptr<VideoSessionInfo> & sessionInfo)327 void SessionCoordinator::AddSession(const sptr<VideoSessionInfo>& sessionInfo)
328 {
329 int32_t userId = sessionInfo->GetUserId();
330 DP_INFO_LOG("add session userId: %{public}d", userId);
331 auto callback = sessionInfo->GetRemoteCallback();
332 if (callback != nullptr) {
333 remoteVideoCallbacksMap_[userId] = callback;
334 ProcessVideoResults(callback);
335 }
336 }
337
DeleteSession(const int32_t userId)338 void SessionCoordinator::DeleteSession(const int32_t userId)
339 {
340 if (remoteVideoCallbacksMap_.count(userId) != 0) {
341 DP_INFO_LOG("delete session userId: %{public}d", userId);
342 remoteVideoCallbacksMap_.erase(userId);
343 }
344 }
345
OnVideoProcessDone(const int32_t userId,const std::string & videoId,const sptr<IPCFileDescriptor> & ipcFd)346 void SessionCoordinator::OnVideoProcessDone(const int32_t userId, const std::string& videoId,
347 const sptr<IPCFileDescriptor> &ipcFd)
348 {
349 DP_INFO_LOG("userId: %{public}d, map size: %{public}d.",
350 userId, static_cast<int32_t>(remoteVideoCallbacksMap_.size()));
351 auto iter = remoteVideoCallbacksMap_.find(userId);
352 if (iter != remoteVideoCallbacksMap_.end()) {
353 auto spCallback = iter->second.promote();
354 DP_CHECK_ERROR_RETURN_LOG(spCallback == nullptr, "OnVideoProcessDone callback is nullptr.");
355 DP_INFO_LOG("videoId: %{public}s", videoId.c_str());
356 spCallback->OnProcessVideoDone(videoId, ipcFd);
357 } else {
358 DP_INFO_LOG("callback is null, videoId: %{public}s.", videoId.c_str());
359 }
360 }
361
OnVideoError(const int32_t userId,const std::string & videoId,DpsError errorCode)362 void SessionCoordinator::OnVideoError(const int32_t userId, const std::string& videoId, DpsError errorCode)
363 {
364 DP_INFO_LOG("userId: %{public}d, map size: %{public}d.",
365 userId, static_cast<int32_t>(remoteVideoCallbacksMap_.size()));
366 auto iter = remoteVideoCallbacksMap_.find(userId);
367 if (iter != remoteVideoCallbacksMap_.end()) {
368 auto spCallback = iter->second.promote();
369 DP_CHECK_ERROR_RETURN_LOG(spCallback == nullptr, "OnVideoError callback is nullptr.");
370 auto error = MapDpsErrorCode(errorCode);
371 DP_INFO_LOG("videoId: %{public}s, error: %{public}d", videoId.c_str(), error);
372 spCallback->OnError(videoId, error);
373 } else {
374 DP_INFO_LOG("callback is null, videoId: %{public}s, errorCode: %{public}d.",
375 videoId.c_str(), errorCode);
376 }
377 }
378
OnVideoStateChanged(const int32_t userId,DpsStatus statusCode)379 void SessionCoordinator::OnVideoStateChanged(const int32_t userId, DpsStatus statusCode)
380 {
381 DP_DEBUG_LOG("entered.");
382 }
383
ProcessVideoResults(sptr<IDeferredVideoProcessingSessionCallback> callback)384 void SessionCoordinator::ProcessVideoResults(sptr<IDeferredVideoProcessingSessionCallback> callback)
385 {
386 DP_DEBUG_LOG("entered.");
387 while (!pendingRequestResults_.empty()) {
388 auto result = pendingRequestResults_.front();
389 if (result.callbackType == CallbackType::ON_PROCESS_DONE) {
390 callback->OnProcessVideoDone(result.requestId, result.ipcFd);
391 }
392 if (result.callbackType == CallbackType::ON_ERROR) {
393 callback->OnError(result.requestId, MapDpsErrorCode(result.errorCode));
394 }
395 if (result.callbackType == CallbackType::ON_STATE_CHANGED) {
396 callback->OnStateChanged(MapDpsStatus(result.statusCode));
397 }
398 pendingRequestResults_.pop_back();
399 }
400 }
401 } // namespace DeferredProcessing
402 } // namespace CameraStandard
403 } // namespace OHOS