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 "photo_post_processor.h"
17
18 #include <sys/mman.h>
19
20 #include "auxiliary_picture.h"
21 #include "buffer_extra_data_impl.h"
22 #include "camera_dynamic_loader.h"
23 #include "dp_log.h"
24 #include "dp_timer.h"
25 #include "dp_utils.h"
26 #include "dps_event_report.h"
27 #include "events_monitor.h"
28 #include "foundation/multimedia/media_library/interfaces/inner_api/media_library_helper/include/photo_proxy.h"
29 #include "iproxy_broker.h"
30 #include "iservmgr_hdi.h"
31 #include "picture_proxy.h"
32 #include "securec.h"
33 #include "v1_3/iimage_process_service.h"
34 #include "v1_3/iimage_process_callback.h"
35 #include "v1_3/types.h"
36
37 namespace OHOS {
38 namespace CameraStandard {
39 namespace DeferredProcessing {
40 namespace {
41 const std::string PHOTO_SERVICE_NAME = "camera_image_process_service";
42 constexpr uint32_t MAX_PROC_TIME_MS = 11 * 1000;
43 constexpr uint32_t MAX_CONSECUTIVE_TIMEOUT_COUNT = 3;
44 constexpr uint32_t MAX_CONSECUTIVE_CRASH_COUNT = 3;
45 constexpr int32_t HDI_VERSION_1 = 1;
46 constexpr int32_t HDI_VERSION_3 = 3;
47 }
48
MapHdiError(OHOS::HDI::Camera::V1_2::ErrorCode errorCode)49 DpsError MapHdiError(OHOS::HDI::Camera::V1_2::ErrorCode errorCode)
50 {
51 DpsError code = DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL;
52 switch (errorCode) {
53 case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_INVALID_ID:
54 code = DpsError::DPS_ERROR_IMAGE_PROC_INVALID_PHOTO_ID;
55 break;
56 case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_PROCESS:
57 code = DpsError::DPS_ERROR_IMAGE_PROC_FAILED;
58 break;
59 case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_TIMEOUT:
60 code = DpsError::DPS_ERROR_IMAGE_PROC_TIMEOUT;
61 break;
62 case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_HIGH_TEMPERATURE:
63 code = DpsError::DPS_ERROR_IMAGE_PROC_HIGH_TEMPERATURE;
64 break;
65 case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_ABNORMAL:
66 code = DpsError::DPS_ERROR_IMAGE_PROC_ABNORMAL;
67 break;
68 case OHOS::HDI::Camera::V1_2::ErrorCode::ERROR_ABORT:
69 code = DpsError::DPS_ERROR_IMAGE_PROC_INTERRUPTED;
70 break;
71 default:
72 DP_ERR_LOG("unexpected error code: %{public}d.", errorCode);
73 break;
74 }
75 return code;
76 }
77
MapHdiStatus(OHOS::HDI::Camera::V1_2::SessionStatus statusCode)78 HdiStatus MapHdiStatus(OHOS::HDI::Camera::V1_2::SessionStatus statusCode)
79 {
80 HdiStatus code = HdiStatus::HDI_DISCONNECTED;
81 switch (statusCode) {
82 case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_READY:
83 code = HdiStatus::HDI_READY;
84 break;
85 case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_READY_SPACE_LIMIT_REACHED:
86 code = HdiStatus::HDI_READY_SPACE_LIMIT_REACHED;
87 break;
88 case OHOS::HDI::Camera::V1_2::SessionStatus::SESSSON_STATUS_NOT_READY_TEMPORARILY:
89 code = HdiStatus::HDI_NOT_READY_TEMPORARILY;
90 break;
91 case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_NOT_READY_OVERHEAT:
92 code = HdiStatus::HDI_NOT_READY_OVERHEAT;
93 break;
94 case OHOS::HDI::Camera::V1_2::SessionStatus::SESSION_STATUS_NOT_READY_PREEMPTED:
95 code = HdiStatus::HDI_NOT_READY_PREEMPTED;
96 break;
97 default:
98 DP_ERR_LOG("unexpected error code: %{public}d.", statusCode);
99 break;
100 }
101 return code;
102 }
103
MapToHdiExecutionMode(ExecutionMode executionMode)104 OHOS::HDI::Camera::V1_2::ExecutionMode MapToHdiExecutionMode(ExecutionMode executionMode)
105 {
106 auto mode = OHOS::HDI::Camera::V1_2::ExecutionMode::LOW_POWER;
107 switch (executionMode) {
108 case ExecutionMode::HIGH_PERFORMANCE:
109 mode = OHOS::HDI::Camera::V1_2::ExecutionMode::HIGH_PREFORMANCE;
110 break;
111 case ExecutionMode::LOAD_BALANCE:
112 mode = OHOS::HDI::Camera::V1_2::ExecutionMode::BALANCED;
113 break;
114 case ExecutionMode::LOW_POWER:
115 mode = OHOS::HDI::Camera::V1_2::ExecutionMode::LOW_POWER;
116 break;
117 default:
118 DP_ERR_LOG("unexpected error code: %{public}d.", executionMode);
119 break;
120 }
121 return mode;
122 }
123
124 class PhotoPostProcessor::PhotoServiceListener : public HDI::ServiceManager::V1_0::ServStatListenerStub {
125 public:
126 using StatusCallback = std::function<void(const HDI::ServiceManager::V1_0::ServiceStatus&)>;
PhotoServiceListener(const std::weak_ptr<PhotoPostProcessor> & processor)127 explicit PhotoServiceListener(const std::weak_ptr<PhotoPostProcessor>& processor) : processor_(processor)
128 {
129 DP_DEBUG_LOG("entered.");
130 }
131
OnReceive(const HDI::ServiceManager::V1_0::ServiceStatus & status)132 void OnReceive(const HDI::ServiceManager::V1_0::ServiceStatus& status)
133 {
134 auto process = processor_.lock();
135 DP_CHECK_ERROR_RETURN_LOG(process == nullptr, "photo post process is nullptr.");
136 process->OnServiceChange(status);
137 }
138
139 private:
140 std::weak_ptr<PhotoPostProcessor> processor_;
141 };
142
143 class PhotoPostProcessor::SessionDeathRecipient : public IRemoteObject::DeathRecipient {
144 public:
SessionDeathRecipient(const std::weak_ptr<PhotoProcessResult> & processResult)145 explicit SessionDeathRecipient(const std::weak_ptr<PhotoProcessResult>& processResult)
146 : processResult_(processResult)
147 {
148 DP_DEBUG_LOG("entered.");
149 }
150
OnRemoteDied(const wptr<IRemoteObject> & remote)151 void OnRemoteDied(const wptr<IRemoteObject> &remote) override
152 {
153 if (auto processResult = processResult_.lock()) {
154 processResult->OnPhotoSessionDied();
155 }
156 }
157
158 private:
159 std::weak_ptr<PhotoProcessResult> processResult_;
160 };
161
162 class PhotoPostProcessor::PhotoProcessListener : public OHOS::HDI::Camera::V1_3::IImageProcessCallback {
163 public:
PhotoProcessListener(const int32_t userId,const std::weak_ptr<PhotoProcessResult> & processResult)164 explicit PhotoProcessListener(const int32_t userId, const std::weak_ptr<PhotoProcessResult>& processResult)
165 : userId_(userId), processResult_(processResult)
166 {
167 DP_DEBUG_LOG("entered.");
168 }
169
170 int32_t OnProcessDone(const std::string& imageId, const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer) override;
171 int32_t OnProcessDoneExt(const std::string& imageId,
172 const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer) override;
173 int32_t OnError(const std::string& imageId, OHOS::HDI::Camera::V1_2::ErrorCode errorCode) override;
174 int32_t OnStatusChanged(OHOS::HDI::Camera::V1_2::SessionStatus status) override;
175
176 private:
177 void ReportEvent(const std::string& imageId);
178 int32_t ProcessBufferInfo(const std::string& imageId, const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer);
179 int32_t ProcessBufferInfoExt(const std::string& imageId,
180 const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer);
181 std::shared_ptr<PictureIntf> AssemblePicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer);
182
183 const int32_t userId_;
184 std::weak_ptr<PhotoProcessResult> processResult_;
185 };
186
OnProcessDone(const std::string & imageId,const OHOS::HDI::Camera::V1_2::ImageBufferInfo & buffer)187 int32_t PhotoPostProcessor::PhotoProcessListener::OnProcessDone(const std::string& imageId,
188 const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer)
189 {
190 DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s", imageId.c_str());
191 auto ret = ProcessBufferInfo(imageId, buffer);
192 if (ret != DP_OK) {
193 DP_ERR_LOG("process done failed imageId: %{public}s.", imageId.c_str());
194 if (auto processResult = processResult_.lock()) {
195 processResult->OnError(imageId, DPS_ERROR_IMAGE_PROC_FAILED);
196 }
197 }
198 return DP_OK;
199 }
200
ProcessBufferInfo(const std::string & imageId,const OHOS::HDI::Camera::V1_2::ImageBufferInfo & buffer)201 int32_t PhotoPostProcessor::PhotoProcessListener::ProcessBufferInfo(const std::string& imageId,
202 const OHOS::HDI::Camera::V1_2::ImageBufferInfo& buffer)
203 {
204 auto bufferHandle = buffer.imageHandle->GetBufferHandle();
205 DP_CHECK_ERROR_RETURN_RET_LOG(bufferHandle == nullptr, DPS_ERROR_IMAGE_PROC_FAILED, "bufferHandle is nullptr.");
206
207 int32_t size = bufferHandle->size;
208 int32_t isDegradedImage = 0;
209 int32_t dataSize = size;
210 uint32_t cloudImageEnhanceFlag = 0;
211 if (buffer.metadata) {
212 int32_t retImageQuality = buffer.metadata->Get("isDegradedImage", isDegradedImage);
213 int32_t retDataSize = buffer.metadata->Get("dataSize", dataSize);
214 int32_t retCloudImageEnhanceFlag = buffer.metadata->Get("cloudImageEnhanceFlag",
215 cloudImageEnhanceFlag);
216 DP_DEBUG_LOG("retImageQuality: %{public}d, retDataSize: %{public}d, retCloudImageEnhanceFlag: %{public}d",
217 static_cast<int>(retImageQuality), static_cast<int>(retDataSize),
218 static_cast<int>(retCloudImageEnhanceFlag));
219 }
220 DP_INFO_LOG("DPS_PHOTO: bufferHandle param, size: %{public}d, dataSize: %{public}d, isDegradedImage: %{public}d",
221 size, static_cast<int>(dataSize), isDegradedImage);
222 auto bufferPtr = std::make_shared<SharedBuffer>(dataSize);
223 DP_CHECK_ERROR_RETURN_RET_LOG(bufferPtr->Initialize() != DP_OK, DPS_ERROR_IMAGE_PROC_FAILED,
224 "failed to initialize shared buffer.");
225
226 auto addr = mmap(nullptr, dataSize, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
227 DP_CHECK_ERROR_RETURN_RET_LOG(addr == MAP_FAILED, DPS_ERROR_IMAGE_PROC_FAILED, "failed to mmap shared buffer.");
228
229 if (bufferPtr->CopyFrom(static_cast<uint8_t*>(addr), dataSize) == DP_OK) {
230 DP_INFO_LOG("DPS_PHOTO: bufferPtr fd: %{public}d, fd: %{public}d, cloudImageEnhanceFlag: %{public}u",
231 bufferHandle->fd, bufferPtr->GetFd(), cloudImageEnhanceFlag);
232 std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(bufferPtr, dataSize,
233 isDegradedImage == 0, cloudImageEnhanceFlag);
234 auto processResult = processResult_.lock();
235 if (processResult) {
236 processResult->OnProcessDone(imageId, bufferInfo);
237 }
238 }
239 munmap(addr, dataSize);
240 ReportEvent(imageId);
241 return DP_OK;
242 }
243
CloneBufferHandle(const BufferHandle * handle)244 BufferHandle *CloneBufferHandle(const BufferHandle *handle)
245 {
246 if (handle == nullptr) {
247 DP_ERR_LOG("%{public}s handle is nullptr", __func__);
248 return nullptr;
249 }
250
251 BufferHandle *newHandle = AllocateBufferHandle(handle->reserveFds, handle->reserveInts);
252 if (newHandle == nullptr) {
253 DP_ERR_LOG("%{public}s AllocateBufferHandle failed, newHandle is nullptr", __func__);
254 return nullptr;
255 }
256
257 if (handle->fd == -1) {
258 newHandle->fd = handle->fd;
259 } else {
260 newHandle->fd = dup(handle->fd);
261 if (newHandle->fd == -1) {
262 DP_ERR_LOG("CloneBufferHandle dup failed");
263 FreeBufferHandle(newHandle);
264 return nullptr;
265 }
266 }
267 newHandle->width = handle->width;
268 newHandle->stride = handle->stride;
269 newHandle->height = handle->height;
270 newHandle->size = handle->size;
271 newHandle->format = handle->format;
272 newHandle->usage = handle->usage;
273 newHandle->phyAddr = handle->phyAddr;
274
275 for (uint32_t i = 0; i < newHandle->reserveFds; i++) {
276 newHandle->reserve[i] = dup(handle->reserve[i]);
277 if (newHandle->reserve[i] == -1) {
278 DP_ERR_LOG("CloneBufferHandle dup reserveFds failed");
279 FreeBufferHandle(newHandle);
280 return nullptr;
281 }
282 }
283
284 if (handle->reserveInts == 0) {
285 DP_ERR_LOG("There is no reserved integer value in old handle, no need to copy");
286 return newHandle;
287 }
288
289 if (memcpy_s(&newHandle->reserve[newHandle->reserveFds], sizeof(int32_t) * newHandle->reserveInts,
290 &handle->reserve[handle->reserveFds], sizeof(int32_t) * handle->reserveInts) != EOK) {
291 DP_ERR_LOG("CloneBufferHandle memcpy_s failed");
292 FreeBufferHandle(newHandle);
293 return nullptr;
294 }
295 return newHandle;
296 }
297
TransBufferHandleToSurfaceBuffer(BufferHandle * bufferHandle)298 sptr<SurfaceBuffer> TransBufferHandleToSurfaceBuffer(BufferHandle *bufferHandle)
299 {
300 DP_DEBUG_LOG("entered");
301 DP_CHECK_ERROR_RETURN_RET_LOG(bufferHandle == nullptr, nullptr, "bufferHandle is nullptr.");
302
303 BufferHandle *newBufferHandle = CloneBufferHandle(bufferHandle);
304 sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
305 surfaceBuffer->SetBufferHandle(newBufferHandle);
306 DP_INFO_LOG("TransBufferHandleToSurfaceBuffer w=%{public}d, h=%{public}d, f=%{public}d",
307 surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), surfaceBuffer->GetFormat());
308 return surfaceBuffer;
309 }
310
SetAuxiliaryPicture(std::shared_ptr<PictureIntf> picture,BufferHandle * bufferHandle,CameraAuxiliaryPictureType type)311 void SetAuxiliaryPicture(std::shared_ptr<PictureIntf> picture, BufferHandle *bufferHandle,
312 CameraAuxiliaryPictureType type)
313 {
314 DP_INFO_LOG("entered, AuxiliaryPictureType type = %{public}d", static_cast<int32_t>(type));
315 DP_CHECK_ERROR_RETURN_LOG(picture == nullptr || bufferHandle == nullptr, "bufferHandle is nullptr.");
316
317 auto buffer = TransBufferHandleToSurfaceBuffer(bufferHandle);
318 picture->SetAuxiliaryPicture(buffer, type);
319 }
320
AssemleAuxilaryPicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer,std::shared_ptr<PictureIntf> & picture)321 void AssemleAuxilaryPicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer,
322 std::shared_ptr<PictureIntf>& picture)
323 {
324 if (buffer.isGainMapValid) {
325 SetAuxiliaryPicture(picture, buffer.gainMapHandle->GetBufferHandle(),
326 CameraAuxiliaryPictureType::GAINMAP);
327 }
328 if (buffer.isDepthMapValid) {
329 SetAuxiliaryPicture(picture, buffer.depthMapHandle->GetBufferHandle(),
330 CameraAuxiliaryPictureType::DEPTH_MAP);
331 }
332 if (buffer.isUnrefocusImageValid) {
333 SetAuxiliaryPicture(picture, buffer.unrefocusImageHandle->GetBufferHandle(),
334 CameraAuxiliaryPictureType::UNREFOCUS_MAP);
335 }
336 if (buffer.isHighBitDepthLinearImageValid) {
337 SetAuxiliaryPicture(picture, buffer.highBitDepthLinearImageHandle->GetBufferHandle(),
338 CameraAuxiliaryPictureType::LINEAR_MAP);
339 }
340 if (buffer.isMakerInfoValid) {
341 auto makerInfoBuffer = TransBufferHandleToSurfaceBuffer(buffer.makerInfoHandle->GetBufferHandle());
342 picture->SetMaintenanceData(makerInfoBuffer);
343 }
344 }
345
AssemblePicture(const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer)346 std::shared_ptr<PictureIntf> PhotoPostProcessor::PhotoProcessListener::AssemblePicture(
347 const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer)
348 {
349 int32_t exifDataSize = 0;
350 if (buffer.metadata) {
351 int32_t retExifDataSize = buffer.metadata->Get("exifDataSize", exifDataSize);
352 DP_INFO_LOG("AssemblePicture retExifDataSize: %{public}d, exifDataSize: %{public}d",
353 retExifDataSize, exifDataSize);
354 }
355 auto imageBuffer = TransBufferHandleToSurfaceBuffer(buffer.imageHandle->GetBufferHandle());
356 DP_CHECK_ERROR_RETURN_RET_LOG(imageBuffer == nullptr, nullptr, "bufferHandle is nullptr.");
357 DP_INFO_LOG("AssemblePicture ImageBufferInfoExt valid: gainMap(%{public}d), depthMap(%{public}d), "
358 "unrefocusMap(%{public}d), linearMap(%{public}d), exif(%{public}d), makeInfo(%{public}d)",
359 buffer.isGainMapValid, buffer.isDepthMapValid, buffer.isUnrefocusImageValid,
360 buffer.isHighBitDepthLinearImageValid, buffer.isExifValid, buffer.isMakerInfoValid);
361 std::shared_ptr<PictureIntf> picture = PictureProxy::CreatePictureProxy();
362 DP_CHECK_ERROR_RETURN_RET_LOG(picture == nullptr, nullptr,
363 "pictureProxy use count is not 1");
364 picture->Create(imageBuffer);
365 DP_CHECK_ERROR_RETURN_RET_LOG(picture == nullptr, nullptr, "picture is nullptr.");
366 if (buffer.isExifValid) {
367 auto exifBuffer = TransBufferHandleToSurfaceBuffer(buffer.exifHandle->GetBufferHandle());
368 sptr<BufferExtraData> extraData = new BufferExtraDataImpl();
369 extraData->ExtraSet("exifDataSize", exifDataSize);
370 if (exifBuffer) {
371 exifBuffer->SetExtraData(extraData);
372 }
373 picture->SetExifMetadata(exifBuffer);
374 }
375 if (picture) {
376 AssemleAuxilaryPicture(buffer, picture);
377 picture->RotatePicture();
378 }
379 return picture;
380 }
381
OnProcessDoneExt(const std::string & imageId,const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer)382 int32_t PhotoPostProcessor::PhotoProcessListener::OnProcessDoneExt(const std::string& imageId,
383 const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer)
384 {
385 DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s", imageId.c_str());
386 auto ret = ProcessBufferInfoExt(imageId, buffer);
387 if (ret != DP_OK) {
388 DP_ERR_LOG("process done failed imageId: %{public}s.", imageId.c_str());
389 if (auto processResult = processResult_.lock()) {
390 processResult->OnError(imageId, DPS_ERROR_IMAGE_PROC_FAILED);
391 }
392 }
393 return DP_OK;
394 }
395
ProcessBufferInfoExt(const std::string & imageId,const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt & buffer)396 int32_t PhotoPostProcessor::PhotoProcessListener::ProcessBufferInfoExt(const std::string& imageId,
397 const OHOS::HDI::Camera::V1_3::ImageBufferInfoExt& buffer)
398 {
399 auto bufferHandle = buffer.imageHandle->GetBufferHandle();
400 DP_CHECK_ERROR_RETURN_RET_LOG(bufferHandle == nullptr, DPS_ERROR_IMAGE_PROC_FAILED, "bufferHandle is nullptr.");
401
402 int size = bufferHandle->size;
403 int32_t isDegradedImage = 0;
404 int32_t dataSize = size;
405 int32_t deferredImageFormat = 0;
406 uint32_t cloudImageEnhanceFlag = 0;
407 if (buffer.metadata) {
408 int32_t retImageQuality = buffer.metadata->Get("isDegradedImage", isDegradedImage);
409 int32_t retDataSize = buffer.metadata->Get("dataSize", dataSize);
410 int32_t retFormat = buffer.metadata->Get("deferredImageFormat", deferredImageFormat);
411 int32_t retCloudImageEnhanceFlag = buffer.metadata->Get("cloudImageEnhanceFlag",
412 cloudImageEnhanceFlag);
413 DP_DEBUG_LOG("retImageQuality: %{public}d, retDataSize: %{public}d, retFormat: %{public}d, "
414 "retCloudImageEnhanceFlag: %{public}d", retImageQuality, retDataSize, retFormat,
415 retCloudImageEnhanceFlag);
416 }
417
418 DP_INFO_LOG("bufferHandle param, bufferHandleSize: %{public}d, dataSize: %{public}d, isDegradedImage: %{public}d, "
419 "deferredImageFormat: %{public}d, cloudImageEnhanceFlag: %{public}u",
420 size, dataSize, isDegradedImage, deferredImageFormat, cloudImageEnhanceFlag);
421 auto processResult = processResult_.lock();
422 if (deferredImageFormat == static_cast<int32_t>(Media::PhotoFormat::YUV)) {
423 std::shared_ptr<PictureIntf> picture = AssemblePicture(buffer);
424 DP_CHECK_ERROR_RETURN_RET_LOG(picture == nullptr, DPS_ERROR_IMAGE_PROC_FAILED,
425 "failed to AssemblePicture.");
426
427 std::shared_ptr<BufferInfoExt> bufferInfo = std::make_shared<BufferInfoExt>(picture, dataSize,
428 isDegradedImage == 0, cloudImageEnhanceFlag);
429 if (processResult) {
430 processResult->OnProcessDoneExt(imageId, bufferInfo);
431 }
432 } else {
433 auto bufferPtr = std::make_shared<SharedBuffer>(dataSize);
434 DP_CHECK_ERROR_RETURN_RET_LOG(bufferPtr->Initialize() != DP_OK, DPS_ERROR_IMAGE_PROC_FAILED,
435 "failed to initialize shared buffer.");
436
437 auto addr = mmap(nullptr, dataSize, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
438 DP_CHECK_ERROR_RETURN_RET_LOG(addr == MAP_FAILED,
439 DPS_ERROR_IMAGE_PROC_FAILED, "failed to mmap shared buffer.");
440 if (bufferPtr->CopyFrom(static_cast<uint8_t*>(addr), dataSize) == DP_OK) {
441 DP_INFO_LOG("DPS_PHOTO: bufferPtr fd: %{public}d, fd: %{public}d", bufferHandle->fd, bufferPtr->GetFd());
442 std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(bufferPtr, dataSize,
443 isDegradedImage == 0, cloudImageEnhanceFlag);
444 if (processResult) {
445 processResult->OnProcessDone(imageId, bufferInfo);
446 }
447 }
448 munmap(addr, dataSize);
449 }
450 ReportEvent(imageId);
451 return DP_OK;
452 }
453
OnError(const std::string & imageId,OHOS::HDI::Camera::V1_2::ErrorCode errorCode)454 int32_t PhotoPostProcessor::PhotoProcessListener::OnError(const std::string& imageId,
455 OHOS::HDI::Camera::V1_2::ErrorCode errorCode)
456 {
457 DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, error: %{public}d", imageId.c_str(), errorCode);
458 if (auto processResult = processResult_.lock()) {
459 DpsError dpsErrorCode = MapHdiError(errorCode);
460 processResult->OnError(imageId, dpsErrorCode);
461 }
462 return DP_OK;
463 }
464
OnStatusChanged(OHOS::HDI::Camera::V1_2::SessionStatus status)465 int32_t PhotoPostProcessor::PhotoProcessListener::OnStatusChanged(OHOS::HDI::Camera::V1_2::SessionStatus status)
466 {
467 DP_INFO_LOG("DPS_PHOTO: HdiStatus: %{public}d", status);
468 if (auto processResult = processResult_.lock()) {
469 HdiStatus hdiStatus = MapHdiStatus(status);
470 processResult->OnStateChanged(hdiStatus);
471 }
472 return DP_OK;
473 }
474
ReportEvent(const std::string & imageId)475 void PhotoPostProcessor::PhotoProcessListener::ReportEvent(const std::string& imageId)
476 {
477 DPSEventReport::GetInstance().UpdateProcessDoneTime(imageId, userId_);
478 }
479
PhotoPostProcessor(const int32_t userId)480 PhotoPostProcessor::PhotoPostProcessor(const int32_t userId)
481 : userId_(userId), serviceListener_(nullptr), processListener_(nullptr), sessionDeathRecipient_(nullptr)
482 {
483 DP_DEBUG_LOG("entered");
484 }
485
~PhotoPostProcessor()486 PhotoPostProcessor::~PhotoPostProcessor()
487 {
488 DP_DEBUG_LOG("entered");
489 DisconnectService();
490 SetPhotoSession(nullptr);
491 runningWork_.clear();
492 imageId2CrashCount_.clear();
493 removeNeededList_.clear();
494 }
495
Initialize()496 void PhotoPostProcessor::Initialize()
497 {
498 DP_DEBUG_LOG("entered");
499 processResult_ = std::make_shared<PhotoProcessResult>(userId_);
500 sessionDeathRecipient_ = sptr<SessionDeathRecipient>::MakeSptr(processResult_);
501 processListener_ = sptr<PhotoProcessListener>::MakeSptr(userId_, processResult_);
502 ConnectService();
503 }
504
GetConcurrency(ExecutionMode mode)505 int32_t PhotoPostProcessor::GetConcurrency(ExecutionMode mode)
506 {
507 int32_t count = 1;
508 auto session = GetPhotoSession();
509 DP_CHECK_ERROR_RETURN_RET_LOG(session == nullptr, count, "photo session is nullptr, count: %{public}d", count);
510
511 int32_t ret = session->GetCoucurrency(OHOS::HDI::Camera::V1_2::ExecutionMode::BALANCED, count);
512 DP_INFO_LOG("DPS_PHOTO: GetCoucurrency to ive, ret: %{public}d", ret);
513 return count;
514 }
515
GetPendingImages(std::vector<std::string> & pendingImages)516 bool PhotoPostProcessor::GetPendingImages(std::vector<std::string>& pendingImages)
517 {
518 auto session = GetPhotoSession();
519 DP_CHECK_ERROR_RETURN_RET_LOG(session == nullptr, false, "photo session is nullptr.");
520
521 int32_t ret = session->GetPendingImages(pendingImages);
522 DP_INFO_LOG("DPS_PHOTO: GetPendingImages to ive, ret: %{public}d", ret);
523 return ret == DP_OK;
524 }
525
SetExecutionMode(ExecutionMode executionMode)526 void PhotoPostProcessor::SetExecutionMode(ExecutionMode executionMode)
527 {
528 auto session = GetPhotoSession();
529 DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
530
531 int32_t ret = session->SetExecutionMode(MapToHdiExecutionMode(executionMode));
532 DP_INFO_LOG("DPS_PHOTO: SetExecutionMode to ive, ret: %{public}d", ret);
533 }
534
SetDefaultExecutionMode()535 void PhotoPostProcessor::SetDefaultExecutionMode()
536 {
537 // 采用直接新增方法,不适配1_2 和 1_3 模式的差异点
538 auto session = GetPhotoSession();
539 DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
540
541 int32_t ret = session->SetExecutionMode(
542 static_cast<OHOS::HDI::Camera::V1_2::ExecutionMode>(OHOS::HDI::Camera::V1_3::ExecutionMode::DEFAULT));
543 DP_INFO_LOG("DPS_PHOTO: SetDefaultExecutionMode to ive, ret: %{public}d", ret);
544 }
545
ProcessImage(const std::string & imageId)546 void PhotoPostProcessor::ProcessImage(const std::string& imageId)
547 {
548 auto session = GetPhotoSession();
549 if (session == nullptr) {
550 DP_ERR_LOG("Failed to process imageId: %{public}s, photo session is nullptr", imageId.c_str());
551 DP_CHECK_EXECUTE(processResult_, processResult_->OnError(imageId, DPS_ERROR_SESSION_NOT_READY_TEMPORARILY));
552 return;
553 }
554
555 StartTimer(imageId);
556 int32_t ret = session->ProcessImage(imageId);
557 DP_INFO_LOG("DPS_PHOTO: Process photo to ive, imageId: %{public}s, ret: %{public}d", imageId.c_str(), ret);
558 }
559
RemoveImage(const std::string & imageId)560 void PhotoPostProcessor::RemoveImage(const std::string& imageId)
561 {
562 auto session = GetPhotoSession();
563 if (session == nullptr) {
564 DP_ERR_LOG("photo session is nullptr.");
565 std::lock_guard<std::mutex> lock(removeMutex_);
566 removeNeededList_.emplace_back(imageId);
567 return;
568 }
569
570 int32_t ret = session->RemoveImage(imageId);
571 DP_INFO_LOG("DPS_PHOTO: Remove photo to ive, imageId: %{public}s, ret: %{public}d", imageId.c_str(), ret);
572 imageId2CrashCount_.erase(imageId);
573 DPSEventReport::GetInstance().UpdateRemoveTime(imageId, userId_);
574 }
575
Interrupt()576 void PhotoPostProcessor::Interrupt()
577 {
578 auto session = GetPhotoSession();
579 DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
580
581 int32_t ret = session->Interrupt();
582 DP_INFO_LOG("DPS_PHOTO: Interrupt photo to ive, ret: %{public}d", ret);
583 }
584
Reset()585 void PhotoPostProcessor::Reset()
586 {
587 auto session = GetPhotoSession();
588 DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "photo session is nullptr.");
589
590 int32_t ret = session->Reset();
591 DP_INFO_LOG("DPS_PHOTO: Reset to ive, ret: %{public}d", ret);
592 consecutiveTimeoutCount_ = 0;
593 }
594
OnProcessDone(const std::string & imageId,const std::shared_ptr<BufferInfo> & bufferInfo)595 void PhotoPostProcessor::OnProcessDone(const std::string& imageId, const std::shared_ptr<BufferInfo>& bufferInfo)
596 {
597 DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, consecutiveTimeoutCount: %{public}d",
598 imageId.c_str(), consecutiveTimeoutCount_.load());
599 consecutiveTimeoutCount_ = 0;
600 StopTimer(imageId);
601 if (auto callback = callback_.lock()) {
602 callback->OnProcessDone(userId_, imageId, bufferInfo);
603 }
604 }
605
OnProcessDoneExt(const std::string & imageId,const std::shared_ptr<BufferInfoExt> & bufferInfo)606 void PhotoPostProcessor::OnProcessDoneExt(const std::string& imageId, const std::shared_ptr<BufferInfoExt>& bufferInfo)
607 {
608 DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, consecutiveTimeoutCount: %{public}d",
609 imageId.c_str(), consecutiveTimeoutCount_.load());
610 consecutiveTimeoutCount_ = 0;
611 StopTimer(imageId);
612 if (auto callback = callback_.lock()) {
613 callback->OnProcessDoneExt(userId_, imageId, bufferInfo);
614 }
615 }
616
OnError(const std::string & imageId,DpsError errorCode)617 void PhotoPostProcessor::OnError(const std::string& imageId, DpsError errorCode)
618 {
619 DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, consecutiveTimeoutCount: %{public}d",
620 imageId.c_str(), consecutiveTimeoutCount_.load());
621 StopTimer(imageId);
622 if (errorCode == DpsError::DPS_ERROR_IMAGE_PROC_TIMEOUT) {
623 consecutiveTimeoutCount_++;
624 if (consecutiveTimeoutCount_ >= static_cast<int>(MAX_CONSECUTIVE_TIMEOUT_COUNT)) {
625 Reset();
626 }
627 } else {
628 consecutiveTimeoutCount_ = 0;
629 }
630
631 if (auto callback = callback_.lock()) {
632 callback->OnError(userId_, imageId, errorCode);
633 }
634 }
635
OnStateChanged(HdiStatus hdiStatus)636 void PhotoPostProcessor::OnStateChanged(HdiStatus hdiStatus)
637 {
638 DP_INFO_LOG("DPS_PHOTO: HdiStatus: %{public}d", hdiStatus);
639 EventsMonitor::GetInstance().NotifyImageEnhanceStatus(hdiStatus);
640 }
641
OnSessionDied()642 void PhotoPostProcessor::OnSessionDied()
643 {
644 DP_INFO_LOG("entered, photo session died!");
645 SetPhotoSession(nullptr);
646 consecutiveTimeoutCount_ = 0;
647 OnStateChanged(HdiStatus::HDI_DISCONNECTED);
648 for (const auto& item : runningWork_) {
649 std::string imageId = item.first;
650 DP_INFO_LOG("Failed to process imageId: %{public}s due to connect service failed", item.first.c_str());
651 if (imageId2CrashCount_.count(item.first) == 0) {
652 imageId2CrashCount_.emplace(item.first, 1);
653 } else {
654 imageId2CrashCount_[item.first] += 1;
655 }
656 DpsError code = DPS_ERROR_SESSION_NOT_READY_TEMPORARILY;
657 if (imageId2CrashCount_[item.first] >= MAX_CONSECUTIVE_CRASH_COUNT) {
658 code = DPS_ERROR_IMAGE_PROC_FAILED;
659 }
660 DP_CHECK_EXECUTE(processResult_, processResult_->OnError(imageId, code));
661 }
662 }
663
SetCallback(const std::weak_ptr<IImageProcessCallbacks> & callback)664 void PhotoPostProcessor::SetCallback(const std::weak_ptr<IImageProcessCallbacks>& callback)
665 {
666 callback_ = callback;
667 }
668
OnTimerOut(const std::string & imageId)669 void PhotoPostProcessor::OnTimerOut(const std::string& imageId)
670 {
671 DP_INFO_LOG("DPS_TIMER: Executed imageId: %{public}s", imageId.c_str());
672 DP_CHECK_EXECUTE(processResult_, processResult_->OnError(imageId, DPS_ERROR_IMAGE_PROC_TIMEOUT));
673 }
674
ConnectService()675 void PhotoPostProcessor::ConnectService()
676 {
677 auto svcMgr = HDI::ServiceManager::V1_0::IServiceManager::Get();
678 DP_CHECK_ERROR_RETURN_LOG(svcMgr == nullptr, "IServiceManager init failed.");
679 serviceListener_ = sptr<PhotoServiceListener>::MakeSptr(weak_from_this());
680 auto ret = svcMgr->RegisterServiceStatusListener(serviceListener_, DEVICE_CLASS_DEFAULT);
681 DP_CHECK_ERROR_RETURN_LOG(ret != 0, "Register Photo ServiceStatusListener failed.");
682 }
683
DisconnectService()684 void PhotoPostProcessor::DisconnectService()
685 {
686 auto session = GetPhotoSession();
687 DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "PhotoSession is nullptr.");
688
689 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IImageProcessSession>(session);
690 bool result = remote->RemoveDeathRecipient(sessionDeathRecipient_);
691 DP_CHECK_ERROR_RETURN_LOG(!result, "Remove DeathRecipient for PhotoProcessSession failed.");
692 auto svcMgr = HDI::ServiceManager::V1_0::IServiceManager::Get();
693 DP_CHECK_ERROR_RETURN_LOG(svcMgr == nullptr, "IServiceManager init failed.");
694
695 auto ret = svcMgr->UnregisterServiceStatusListener(serviceListener_);
696 DP_CHECK_ERROR_RETURN_LOG(ret != 0, "Unregister Photo ServiceStatusListener failed.");
697 }
698
OnServiceChange(const HDI::ServiceManager::V1_0::ServiceStatus & status)699 void PhotoPostProcessor::OnServiceChange(const HDI::ServiceManager::V1_0::ServiceStatus& status)
700 {
701 DP_CHECK_RETURN(status.serviceName != PHOTO_SERVICE_NAME);
702 DP_CHECK_RETURN_LOG(status.status != HDI::ServiceManager::V1_0::SERVIE_STATUS_START,
703 "photo service state: %{public}d", status.status);
704 DP_CHECK_RETURN(GetPhotoSession() != nullptr);
705
706 sptr<OHOS::HDI::Camera::V1_2::IImageProcessService> proxyV1_2 =
707 OHOS::HDI::Camera::V1_2::IImageProcessService::Get(status.serviceName);
708 DP_CHECK_ERROR_RETURN_LOG(proxyV1_2 == nullptr, "get ImageProcessService failed.");
709
710 uint32_t majorVer = 0;
711 uint32_t minorVer = 0;
712 proxyV1_2->GetVersion(majorVer, minorVer);
713 int32_t versionId = GetVersionId(majorVer, minorVer);
714 sptr<IImageProcessSession> session;
715 sptr<OHOS::HDI::Camera::V1_3::IImageProcessService> proxyV1_3;
716 if (versionId >= GetVersionId(HDI_VERSION_1, HDI_VERSION_3)) {
717 proxyV1_3 = OHOS::HDI::Camera::V1_3::IImageProcessService::CastFrom(proxyV1_2);
718 }
719 if (proxyV1_3 != nullptr) {
720 DP_INFO_LOG("CreateImageProcessSessionExt version=%{public}d_%{public}d", majorVer, minorVer);
721 proxyV1_3->CreateImageProcessSessionExt(userId_, processListener_, session);
722 } else {
723 DP_INFO_LOG("CreateImageProcessSession version=%{public}d_%{public}d", majorVer, minorVer);
724 proxyV1_2->CreateImageProcessSession(userId_, processListener_, session);
725 }
726 DP_CHECK_ERROR_RETURN_LOG(session == nullptr, "get ImageProcessSession failed.");
727
728 const sptr<IRemoteObject>& remote = OHOS::HDI::hdi_objcast<IImageProcessSession>(session);
729 bool result = remote->AddDeathRecipient(sessionDeathRecipient_);
730 DP_CHECK_ERROR_RETURN_LOG(!result, "add DeathRecipient for ImageProcessSession failed.");
731
732 RemoveNeedJbo(session);
733 SetPhotoSession(session);
734 OnStateChanged(HdiStatus::HDI_READY);
735 }
736
RemoveNeedJbo(const sptr<IImageProcessSession> & session)737 void PhotoPostProcessor::RemoveNeedJbo(const sptr<IImageProcessSession>& session)
738 {
739 std::lock_guard<std::mutex> lock(removeMutex_);
740 for (const auto& imageId : removeNeededList_) {
741 int32_t ret = session->RemoveImage(imageId);
742 DP_INFO_LOG("DPS_PHOTO: RemoveImage imageId: %{public}s, ret: %{public}d", imageId.c_str(), ret);
743 }
744 removeNeededList_.clear();
745 }
746
StartTimer(const std::string & imageId)747 void PhotoPostProcessor::StartTimer(const std::string& imageId)
748 {
749 uint32_t timeId = DpsTimer::GetInstance().StartTimer([&, imageId]() {OnTimerOut(imageId);}, MAX_PROC_TIME_MS);
750 DP_INFO_LOG("DPS_TIMER: Start imageId: %{public}s, timeId: %{public}u", imageId.c_str(), timeId);
751 runningWork_.emplace(imageId, timeId);
752 }
753
StopTimer(const std::string & imageId)754 void PhotoPostProcessor::StopTimer(const std::string& imageId)
755 {
756 auto it = runningWork_.find(imageId);
757 DP_CHECK_ERROR_RETURN_LOG(it == runningWork_.end(),
758 "Stoptimer failed not find imageId: %{public}s", imageId.c_str());
759
760 DpsTimer::GetInstance().StopTimer(it->second);
761 DP_INFO_LOG("DPS_TIMER: Stop imageId: %{public}s, timeId: %{public}u", imageId.c_str(), it->second);
762 runningWork_.erase(it);
763 }
764 } // namespace DeferredProcessing
765 } // namespace CameraStandard
766 } // namespace OHOS