1 /*
2  * Copyright (c) 2023-2024 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 "screen_decision_center.h"
17 
18 #include "dscreen_constants.h"
19 #include "dscreen_errcode.h"
20 #include "dscreen_log.h"
21 
22 namespace OHOS {
23 namespace DistributedHardware {
IsDirtyRectValid(const std::vector<OHOS::Rect> & damages)24 bool ScreenDecisionCenter::IsDirtyRectValid(const std::vector<OHOS::Rect> &damages)
25 {
26     DHLOGI("%{public}s: IsDirtyRectValid.", DSCREEN_LOG_TAG);
27     if (damages.empty()) {
28         DHLOGE("%{public}s: damages size is empty.", DSCREEN_LOG_TAG);
29         return false;
30     }
31     int32_t screenWidth = static_cast<int32_t>(configParam_.GetScreenWidth());
32     int32_t screenHeight = static_cast<int32_t>(configParam_.GetScreenHeight());
33     for (const auto &damage : damages) {
34         if (damage.x < 0 || damage.x > screenWidth || damage.y < 0 ||
35             damage.y > screenHeight || damage.x % TWO == 1 || damage.w % TWO == 1) {
36             DHLOGE("%{public}s: dirty x:%{public}" PRId32 ", y:%{public}" PRId32 ", w:%{public}" PRId32
37                 ", h:%{public}" PRId32, DSCREEN_LOG_TAG, damage.x, damage.y, damage.w, damage.h);
38             return false;
39         }
40         int32_t width = screenWidth - damage.x;
41         int32_t height = screenHeight - damage.y;
42         if (damage.w < 0 || damage.w > width || damage.h < 0 || damage.h > height) {
43             DHLOGE("%{public}s: dirty x:%{public}" PRId32 ", y:%{public}" PRId32 ", w:%{public}" PRId32
44                 ", h:%{public}" PRId32,
45                 DSCREEN_LOG_TAG, damage.x, damage.y, damage.w, damage.h);
46             return false;
47         }
48     }
49     return true;
50 }
51 
JudgeDirtyThreshold(const std::vector<OHOS::Rect> & damages)52 bool ScreenDecisionCenter::JudgeDirtyThreshold(const std::vector<OHOS::Rect> &damages)
53 {
54     DHLOGI("%{public}s: JudgeDirtyThreshold.", DSCREEN_LOG_TAG);
55     int32_t allDirtyArea = 0;
56     for (const auto &damage : damages) {
57         allDirtyArea += damage.w * damage.h;
58         if (allDirtyArea > DIRTY_REGION_ARE_THRESHOLD) {
59             DHLOGE("%{public}s: dirtyArea is %{public}" PRId32, DSCREEN_LOG_TAG, allDirtyArea);
60             return false;
61         }
62     }
63     return true;
64 }
65 
LimitTime(uint32_t timethreshold)66 bool ScreenDecisionCenter::LimitTime(uint32_t timethreshold)
67 {
68     return difftime(time(nullptr), sendFullTime_) >= timethreshold;
69 }
70 
InputBufferImage(sptr<SurfaceBuffer> & surfaceBuffer,const std::vector<OHOS::Rect> & damages)71 int32_t ScreenDecisionCenter::InputBufferImage(sptr<SurfaceBuffer> &surfaceBuffer,
72     const std::vector<OHOS::Rect> &damages)
73 {
74     DHLOGI("%{public}s: InputBufferImage.", DSCREEN_LOG_TAG);
75     if (surfaceBuffer == nullptr) {
76         DHLOGE("%{public}s: surfaceBuffer is null.", DSCREEN_LOG_TAG);
77         return ERR_DH_SCREEN_SURFACE_BUFFER_INVALIED;
78     }
79     if (damages.empty() || frameCount_ < MIN_SURPPORT_FRAME_COUNT ||
80         LimitTime(FORCE_FULL_IMAGE_TIME_INTERAL) ||
81         !IsDirtyRectValid(damages) || !JudgeDirtyThreshold(damages)) {
82         DHLOGI("%{public}s: send full image data.", DSCREEN_LOG_TAG);
83         sendFullTime_ = time(nullptr);
84         int32_t ret = imageProcessor_->ProcessFullImage(surfaceBuffer);
85         if (ret != DH_SUCCESS) {
86             DHLOGE("%{public}s: send full data failed.", DSCREEN_LOG_TAG);
87             return ret;
88         }
89     } else {
90         DHLOGI("%{public}s: send dirty data.", DSCREEN_LOG_TAG);
91         int32_t ret = imageJpeg_->ProcessDamageSurface(surfaceBuffer, damages);
92         if (ret != DH_SUCCESS) {
93             DHLOGE("%{public}s: send dirty data failed.", DSCREEN_LOG_TAG);
94             return ret;
95         }
96     }
97     frameCount_++;
98     return DH_SUCCESS;
99 }
100 
ConfigureDecisionCenter(std::shared_ptr<IImageSourceProcessorListener> & listener,std::shared_ptr<IImageSourceProcessor> & imageProcessor)101 int32_t ScreenDecisionCenter::ConfigureDecisionCenter(std::shared_ptr<IImageSourceProcessorListener> &listener,
102     std::shared_ptr<IImageSourceProcessor> &imageProcessor)
103 {
104     DHLOGI("%{public}s: ConfigureDecisionCenter.", DSCREEN_LOG_TAG);
105     if (listener == nullptr || imageProcessor == nullptr) {
106         DHLOGE("%{public}s: Image source process is null.", DSCREEN_LOG_TAG);
107         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
108     }
109     imageJpeg_ = std::make_shared<JpegImageProcessor>(configParam_);
110     imageJpeg_->SetImageProcessListener(listener);
111     imageProcessor_ = imageProcessor;
112     return DH_SUCCESS;
113 }
114 
SetJpegSurface(sptr<Surface> & surface)115 int32_t ScreenDecisionCenter::SetJpegSurface(sptr<Surface> &surface)
116 {
117     DHLOGI("%{public}s: SetJpegSurface.", DSCREEN_LOG_TAG);
118     if (surface == nullptr) {
119         DHLOGE("%{public}s: Jpeg source is null.", DSCREEN_LOG_TAG);
120         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
121     }
122     return imageJpeg_->SetOutputSurface(surface);
123 }
124 } // namespace DistributedHardware
125 } // namespace OHOS