• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "render/rs_colorspace_convert.h"
16 
17 #include <dlfcn.h>
18 
19 #include "effect/image_filter.h"
20 #include "luminance/rs_luminance_control.h"
21 #include "metadata_helper.h"
22 #include "platform/common/rs_log.h"
23 
24 namespace OHOS {
25 namespace Rosen {
26 
27 namespace {
28 constexpr float DEFAULT_HDR_RATIO = 1.0f;
29 constexpr float REFERENCE_WHITE = 203.0f;
30 constexpr float CAMERA_WHITE_MIN = 500.0f;
31 constexpr float CAMERA_WHITE_MAX = 510.0f;
32 constexpr float CAMERA_HDR_RATIO = 2.5f;
33 constexpr float HDR_WHITE = 1000.0f;
34 constexpr float DEFAULT_SCALER = HDR_WHITE / REFERENCE_WHITE;
35 
CalScaler(const float & maxContentLightLevel)36 float CalScaler(const float& maxContentLightLevel)
37 {
38     if (ROSEN_EQ(maxContentLightLevel, REFERENCE_WHITE)) {
39         return DEFAULT_HDR_RATIO;
40     } else if (ROSEN_GE(maxContentLightLevel, CAMERA_WHITE_MIN) && ROSEN_LE(maxContentLightLevel, CAMERA_WHITE_MAX)) {
41         return CAMERA_HDR_RATIO;
42     } else if (ROSEN_LE(maxContentLightLevel, HDR_WHITE)) {
43         return HDR_WHITE / REFERENCE_WHITE;
44     } else {
45         return maxContentLightLevel / REFERENCE_WHITE;
46     }
47 }
48 }; // namespace
49 
RSColorSpaceConvert()50 RSColorSpaceConvert::RSColorSpaceConvert()
51 {
52     handle_ = dlopen("libvideoprocessingengine.z.so", RTLD_LAZY);
53     if (handle_ == nullptr) {
54         RS_LOGW("[%{public}s]:load library failed, reason: %{public}s", __func__, dlerror());
55         return;
56     }
57     colorSpaceConvertDisplayCreate_ = reinterpret_cast<VPEColorSpaceConvertDisplayCreate>(
58         dlsym(handle_, "ColorSpaceConvertDisplayCreate"));
59     if (colorSpaceConvertDisplayCreate_ == nullptr) {
60         RS_LOGW("[%{public}s]:load func failed, reason: %{public}s", __func__, dlerror());
61         if (dlclose(handle_) != 0) {
62             ROSEN_LOGE("Could not close the handle. This indicates a leak. %{public}s", dlerror());
63         }
64         handle_ = nullptr;
65         return;
66     }
67     colorSpaceConvertDisplayDestroy_ = reinterpret_cast<VPEColorSpaceConvertDisplayDestroy>(
68         dlsym(handle_, "ColorSpaceConvertDisplayDestroy"));
69     if (colorSpaceConvertDisplayDestroy_ == nullptr) {
70         RS_LOGW("[%{public}s]:load func failed, reason: %{public}s", __func__, dlerror());
71         if (dlclose(handle_) != 0) {
72             ROSEN_LOGE("Could not close the handle. This indicates a leak. %{public}s", dlerror());
73         }
74         handle_ = nullptr;
75         return;
76     }
77     colorSpaceConvertDisplayHandle_ = colorSpaceConvertDisplayCreate_();
78     if (colorSpaceConvertDisplayHandle_ == nullptr) {
79         RS_LOGE("ColorSpaceConvertDisplayCreate failed, return nullptr");
80         if (dlclose(handle_) != 0) {
81             ROSEN_LOGE("Could not close the handle. This indicates a leak. %{public}s", dlerror());
82         }
83         handle_ = nullptr;
84         return;
85     }
86     colorSpaceConverterDisplay_ = static_cast<ColorSpaceConvertDisplayHandleImpl *>(
87         colorSpaceConvertDisplayHandle_)->obj;
88 }
89 
~RSColorSpaceConvert()90 RSColorSpaceConvert::~RSColorSpaceConvert()
91 {
92     if (colorSpaceConvertDisplayHandle_) {
93         colorSpaceConvertDisplayDestroy_(colorSpaceConvertDisplayHandle_);
94         colorSpaceConvertDisplayHandle_ = nullptr;
95     }
96     if (handle_) {
97         if (dlclose(handle_) != 0) {
98             ROSEN_LOGE("Could not close the handle. This indicates a leak. %{public}s", dlerror());
99         }
100         handle_ = nullptr;
101     }
102     colorSpaceConvertDisplayCreate_ = nullptr;
103     colorSpaceConvertDisplayDestroy_ = nullptr;
104     colorSpaceConverterDisplay_ = nullptr;
105 }
106 
Instance()107 RSColorSpaceConvert& RSColorSpaceConvert::Instance()
108 {
109     static RSColorSpaceConvert instance;
110     return instance;
111 }
112 
ColorSpaceConvertor(std::shared_ptr<Drawing::ShaderEffect> inputShader,const sptr<SurfaceBuffer> & surfaceBuffer,Drawing::Paint & paint,GraphicColorGamut targetColorSpace,ScreenId screenId,uint32_t dynamicRangeMode)113 bool RSColorSpaceConvert::ColorSpaceConvertor(std::shared_ptr<Drawing::ShaderEffect> inputShader,
114     const sptr<SurfaceBuffer>& surfaceBuffer, Drawing::Paint& paint, GraphicColorGamut targetColorSpace,
115     ScreenId screenId, uint32_t dynamicRangeMode)
116 {
117     RS_LOGD("RSColorSpaceConvertor targetColorSpace:%{public}d. screenId:%{public}" PRIu64 ". \
118         dynamicRangeMode%{public}u", targetColorSpace, screenId, dynamicRangeMode);
119     VPEParameter parameter;
120 
121     if (inputShader == nullptr) {
122         RS_LOGE("bhdr imageShader is nullptr.");
123         return false;
124     }
125 
126     if (!SetColorSpaceConverterDisplayParameter(surfaceBuffer, parameter, targetColorSpace, screenId,
127         dynamicRangeMode)) {
128         return false;
129     }
130     if (dynamicRangeMode == DynamicRangeMode::STANDARD) {
131         parameter.disableHeadRoom = true;
132     }
133 
134     std::shared_ptr<Drawing::ShaderEffect> outputShader;
135 
136     if (colorSpaceConverterDisplay_ == nullptr) {
137         RS_LOGE("colorSpaceConverterDisplay_ is nullptr.");
138         return false;
139     }
140     auto convRet = colorSpaceConverterDisplay_->Process(inputShader, outputShader, parameter);
141     if (convRet != Media::VideoProcessingEngine::VPE_ALGO_ERR_OK) {
142         RS_LOGE("bhdr failed with %{public}u.", convRet);
143         return false;
144     }
145     if (outputShader == nullptr) {
146         RS_LOGE("bhdr outputShader is nullptr.");
147         return false;
148     }
149     paint.SetShaderEffect(outputShader);
150     return true;
151 }
152 
SetColorSpaceConverterDisplayParameter(const sptr<SurfaceBuffer> & surfaceBuffer,VPEParameter & parameter,GraphicColorGamut targetColorSpace,ScreenId screenId,uint32_t dynamicRangeMode)153 bool RSColorSpaceConvert::SetColorSpaceConverterDisplayParameter(const sptr<SurfaceBuffer>& surfaceBuffer,
154     VPEParameter& parameter, GraphicColorGamut targetColorSpace, ScreenId screenId, uint32_t dynamicRangeMode)
155 {
156     using namespace HDIV;
157 
158     GSError ret = MetadataHelper::GetColorSpaceInfo(surfaceBuffer, parameter.inputColorSpace.colorSpaceInfo);
159     if (ret != GSERROR_OK) {
160         RS_LOGE("bhdr GetColorSpaceInfo failed with %{public}u.", ret);
161         return false;
162     }
163     if (!ConvertColorGamutToSpaceInfo(targetColorSpace, parameter.outputColorSpace.colorSpaceInfo)) {
164         return false;
165     }
166     CM_HDR_Metadata_Type hdrMetadataType = CM_METADATA_NONE;
167     ret = MetadataHelper::GetHDRMetadataType(surfaceBuffer, hdrMetadataType);
168     if (ret != GSERROR_OK) {
169         RS_LOGD("bhdr GetHDRMetadataType failed with %{public}u.", ret);
170     }
171     parameter.inputColorSpace.metadataType = hdrMetadataType;
172     parameter.outputColorSpace.metadataType = hdrMetadataType;
173 
174     ret = MetadataHelper::GetHDRStaticMetadata(surfaceBuffer, parameter.staticMetadata);
175     if (ret != GSERROR_OK) {
176         RS_LOGD("bhdr GetHDRStaticMetadata failed with %{public}u.", ret);
177     }
178 
179     float scaler = DEFAULT_SCALER;
180     if (parameter.staticMetadata.size() != sizeof(HdrStaticMetadata)) {
181         RS_LOGD("bhdr parameter.staticMetadata size is invalid");
182     } else {
183         const auto& data = *reinterpret_cast<HdrStaticMetadata*>(parameter.staticMetadata.data());
184         scaler = CalScaler(data.cta861.maxContentLightLevel);
185     }
186 
187     ret = MetadataHelper::GetHDRDynamicMetadata(surfaceBuffer, parameter.dynamicMetadata);
188     if (ret != GSERROR_OK) {
189         RS_LOGD("bhdr GetHDRDynamicMetadata failed with %{public}u.", ret);
190     }
191 
192     // Set brightness to screen brightness when HDR Vivid, otherwise 500 nits
193     float sdrNits = RSLuminanceControl::Get().GetSdrDisplayNits(screenId);
194     float displayNits = RSLuminanceControl::Get().GetDisplayNits(screenId);
195     parameter.tmoNits = std::clamp(sdrNits * scaler, sdrNits, displayNits);
196     parameter.currentDisplayNits = displayNits;
197     parameter.sdrNits = sdrNits;
198     RS_LOGD("bhdr TmoNits:%{public}f. DisplayNits:%{public}f. SdrNits:%{public}f.", parameter.tmoNits,
199         parameter.currentDisplayNits, parameter.sdrNits);
200     return true;
201 }
202 
ConvertColorGamutToSpaceInfo(const GraphicColorGamut & colorGamut,HDIV::CM_ColorSpaceInfo & colorSpaceInfo)203 bool RSColorSpaceConvert::ConvertColorGamutToSpaceInfo(const GraphicColorGamut& colorGamut,
204     HDIV::CM_ColorSpaceInfo& colorSpaceInfo)
205 {
206     using namespace HDIV;
207     static const std::map<GraphicColorGamut, CM_ColorSpaceType> RS_TO_COMMON_COLOR_SPACE_TYPE_MAP {
208         {GRAPHIC_COLOR_GAMUT_STANDARD_BT601, CM_BT601_EBU_FULL},
209         {GRAPHIC_COLOR_GAMUT_STANDARD_BT709, CM_BT709_FULL},
210         {GRAPHIC_COLOR_GAMUT_SRGB, CM_SRGB_FULL},
211         {GRAPHIC_COLOR_GAMUT_ADOBE_RGB, CM_ADOBERGB_FULL},
212         {GRAPHIC_COLOR_GAMUT_DISPLAY_P3, CM_P3_FULL},
213         {GRAPHIC_COLOR_GAMUT_BT2020, CM_DISPLAY_BT2020_SRGB},
214         {GRAPHIC_COLOR_GAMUT_BT2100_PQ, CM_BT2020_PQ_FULL},
215         {GRAPHIC_COLOR_GAMUT_BT2100_HLG, CM_BT2020_HLG_FULL},
216         {GRAPHIC_COLOR_GAMUT_DISPLAY_BT2020, CM_DISPLAY_BT2020_SRGB},
217     };
218 
219     CM_ColorSpaceType colorSpaceType = CM_COLORSPACE_NONE;
220     if (RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.find(colorGamut) != RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.end()) {
221         colorSpaceType = RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.at(colorGamut);
222     }
223 
224     GSError ret = MetadataHelper::ConvertColorSpaceTypeToInfo(colorSpaceType, colorSpaceInfo);
225     if (ret != GSERROR_OK) {
226         RS_LOGE("bhdr ConvertColorSpaceTypeToInfo failed with %{public}u.", ret);
227         return false;
228     }
229 
230     return true;
231 }
232 
233 } // namespace Rosen
234 } // namespace OHOS
235