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