• 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 
16 #include "colorspace_helper.h"
17 
18 #include <unordered_map>
19 
20 #include "metadata_helper.h"
21 #include "colorspace_converter.h"
22 #include "metadata_generator.h"
23 #include "effect_log.h"
24 
25 namespace OHOS {
26 namespace Media {
27 namespace Effect {
28 using namespace OHOS::ColorManager;
29 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
30 
31 static const std::unordered_map<EffectColorSpace, ColorSpaceName> EFFECT_TO_COLORMANAGER_COLORSPACE_MAP = {
32     { EffectColorSpace::SRGB, ColorSpaceName::SRGB },
33     { EffectColorSpace::SRGB_LIMIT, ColorSpaceName::SRGB_LIMIT },
34     { EffectColorSpace::DISPLAY_P3, ColorSpaceName::DISPLAY_P3 },
35     { EffectColorSpace::DISPLAY_P3_LIMIT, ColorSpaceName::DISPLAY_P3_LIMIT },
36     { EffectColorSpace::BT2020_HLG, ColorSpaceName::BT2020_HLG },
37     { EffectColorSpace::BT2020_HLG_LIMIT, ColorSpaceName::BT2020_HLG_LIMIT },
38     { EffectColorSpace::BT2020_PQ, ColorSpaceName::BT2020_PQ },
39     { EffectColorSpace::BT2020_PQ_LIMIT, ColorSpaceName::BT2020_PQ_LIMIT },
40     { EffectColorSpace::ADOBE_RGB, ColorSpaceName::ADOBE_RGB },
41 };
42 
43 static const std::unordered_map<EffectColorSpace, CM_ColorSpaceType> EFFECT_TO_GRAPHIC_COLORSPACE_MAP = {
44     { EffectColorSpace::SRGB, CM_ColorSpaceType::CM_SRGB_FULL },
45     { EffectColorSpace::SRGB_LIMIT, CM_ColorSpaceType::CM_SRGB_LIMIT },
46     { EffectColorSpace::DISPLAY_P3, CM_ColorSpaceType::CM_P3_FULL },
47     { EffectColorSpace::DISPLAY_P3_LIMIT, CM_ColorSpaceType::CM_P3_LIMIT },
48     { EffectColorSpace::BT2020_HLG, CM_ColorSpaceType::CM_BT2020_HLG_FULL },
49     { EffectColorSpace::BT2020_HLG_LIMIT, CM_ColorSpaceType::CM_BT2020_HLG_LIMIT },
50     { EffectColorSpace::BT2020_PQ, CM_ColorSpaceType::CM_BT2020_PQ_FULL },
51     { EffectColorSpace::BT2020_PQ_LIMIT, CM_ColorSpaceType::CM_BT2020_PQ_LIMIT },
52     { EffectColorSpace::ADOBE_RGB, CM_ColorSpaceType::CM_ADOBERGB_FULL },
53 };
54 
55 static const std::unordered_map<EffectColorSpace, OH_NativeBuffer_ColorSpace> EFFECT_TO_NATIVE_BUFFER_COLORSPACE_MAP = {
56     { EffectColorSpace::SRGB, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_SRGB_FULL },
57     { EffectColorSpace::SRGB_LIMIT, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_SRGB_LIMIT },
58     { EffectColorSpace::DISPLAY_P3, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_P3_FULL },
59     { EffectColorSpace::DISPLAY_P3_LIMIT, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_P3_LIMIT },
60     { EffectColorSpace::BT2020_HLG, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_BT2020_HLG_FULL },
61     { EffectColorSpace::BT2020_HLG_LIMIT, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_BT2020_HLG_LIMIT },
62     { EffectColorSpace::BT2020_PQ, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_BT2020_PQ_FULL },
63     { EffectColorSpace::BT2020_PQ_LIMIT, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_BT2020_PQ_LIMIT },
64     { EffectColorSpace::ADOBE_RGB, OH_NativeBuffer_ColorSpace::OH_COLORSPACE_ADOBERGB_FULL },
65 };
66 
IsHdrColorSpace(EffectColorSpace colorSpace)67 bool ColorSpaceHelper::IsHdrColorSpace(EffectColorSpace colorSpace)
68 {
69     return colorSpace == EffectColorSpace::BT2020_HLG || colorSpace == EffectColorSpace::BT2020_HLG_LIMIT ||
70         colorSpace == EffectColorSpace::BT2020_PQ || colorSpace == EffectColorSpace::BT2020_PQ_LIMIT;
71 }
72 
ConvertToEffectColorSpace(ColorSpaceName colorSpaceName)73 EffectColorSpace ColorSpaceHelper::ConvertToEffectColorSpace(ColorSpaceName colorSpaceName)
74 {
75     EffectColorSpace colorSpaceType = EffectColorSpace::DEFAULT;
76 
77     for (const auto &it : EFFECT_TO_COLORMANAGER_COLORSPACE_MAP) {
78         if (it.second == colorSpaceName) {
79             colorSpaceType = it.first;
80             break;
81         }
82     }
83 
84     EFFECT_LOGD("ConvertToEffectColorSpace: colorSpaceName=%{public}d, effectColorSpaceType=%{public}d",
85         colorSpaceName, colorSpaceType);
86     return colorSpaceType;
87 }
88 
ConvertToNativeBufferColorSpace(EffectColorSpace effectColorSpace)89 OH_NativeBuffer_ColorSpace ColorSpaceHelper::ConvertToNativeBufferColorSpace(EffectColorSpace effectColorSpace)
90 {
91     OH_NativeBuffer_ColorSpace nativeBufferColorSpace = OH_NativeBuffer_ColorSpace::OH_COLORSPACE_NONE;
92     auto it = EFFECT_TO_NATIVE_BUFFER_COLORSPACE_MAP.find(effectColorSpace);
93     if (it != EFFECT_TO_NATIVE_BUFFER_COLORSPACE_MAP.end()) {
94         nativeBufferColorSpace = it->second;
95     }
96 
97     EFFECT_LOGD("ConvertToEffectColorSpace: colorSpaceType=%{public}d, effectColorSpaceType=%{public}d",
98         effectColorSpace, nativeBufferColorSpace);
99     return nativeBufferColorSpace;
100 }
101 
ConvertToColorSpaceName(EffectColorSpace colorSpace)102 ColorSpaceName ColorSpaceHelper::ConvertToColorSpaceName(EffectColorSpace colorSpace)
103 {
104     ColorSpaceName colorSpaceName = ColorSpaceName::NONE;
105     auto it = EFFECT_TO_COLORMANAGER_COLORSPACE_MAP.find(colorSpace);
106     if (it != EFFECT_TO_COLORMANAGER_COLORSPACE_MAP.end()) {
107         colorSpaceName =  it->second;
108     }
109 
110     return colorSpaceName;
111 }
112 
ConvertToEffectColorSpace(CM_ColorSpaceType type)113 EffectColorSpace ColorSpaceHelper::ConvertToEffectColorSpace(CM_ColorSpaceType type)
114 {
115     EffectColorSpace effectColorSpaceType = EffectColorSpace::DEFAULT;
116 
117     for (const auto &it : EFFECT_TO_GRAPHIC_COLORSPACE_MAP) {
118         if (it.second == type) {
119             effectColorSpaceType = it.first;
120             break;
121         }
122     }
123 
124     EFFECT_LOGD("ConvertToEffectColorSpace: colorSpaceType=%{public}d, effectColorSpaceType=%{public}d",
125         type, effectColorSpaceType);
126     return effectColorSpaceType;
127 }
128 
ConvertToCMColorSpace(EffectColorSpace colorSpace)129 CM_ColorSpaceType ColorSpaceHelper::ConvertToCMColorSpace(EffectColorSpace colorSpace)
130 {
131     CM_ColorSpaceType cmColorSpaceType = CM_ColorSpaceType::CM_COLORSPACE_NONE;
132     auto it = EFFECT_TO_GRAPHIC_COLORSPACE_MAP.find(colorSpace);
133     if (it != EFFECT_TO_GRAPHIC_COLORSPACE_MAP.end()) {
134         cmColorSpaceType =  it->second;
135     }
136 
137     return cmColorSpaceType;
138 }
139 
SetSurfaceBufferMetadataType(SurfaceBuffer * sb,const CM_HDR_Metadata_Type & type)140 ErrorCode ColorSpaceHelper::SetSurfaceBufferMetadataType(SurfaceBuffer *sb, const CM_HDR_Metadata_Type &type)
141 {
142     sptr<SurfaceBuffer> buffer = sb;
143     auto res = MetadataHelper::SetHDRMetadataType(buffer, type);
144     CHECK_AND_RETURN_RET_LOG(res == GSError::GSERROR_OK, ErrorCode::ERR_SET_METADATA_FAIL,
145         "SetSurfaceBufferMetadataType: SetHDRMetadataType fail! res=%{public}d", res);
146     return ErrorCode::SUCCESS;
147 }
148 
GetSurfaceBufferMetadataType(SurfaceBuffer * sb,CM_HDR_Metadata_Type & type)149 ErrorCode ColorSpaceHelper::GetSurfaceBufferMetadataType(SurfaceBuffer *sb, CM_HDR_Metadata_Type &type)
150 {
151     sptr<SurfaceBuffer> buffer = sb;
152     auto res = MetadataHelper::GetHDRMetadataType(buffer, type);
153     CHECK_AND_RETURN_RET_LOG(res == GSError::GSERROR_OK, ErrorCode::ERR_GET_METADATA_FAIL,
154         "GetSurfaceBufferMetadataType: GetHDRMetadataType fail! res=%{public}d", res);
155     return ErrorCode::SUCCESS;
156 }
157 
SetSurfaceBufferColorSpaceType(SurfaceBuffer * sb,const CM_ColorSpaceType & type)158 ErrorCode ColorSpaceHelper::SetSurfaceBufferColorSpaceType(SurfaceBuffer *sb, const CM_ColorSpaceType &type)
159 {
160     sptr<SurfaceBuffer> buffer = sb;
161     auto res = MetadataHelper::SetColorSpaceType(buffer, type);
162     CHECK_AND_RETURN_RET_LOG(res == GSError::GSERROR_OK, ErrorCode::ERR_SET_COLORSPACETYPE_FAIL,
163         "SetSurfaceBufferColorSpaceType: SetColorSpaceType fail! res=%{public}d", res);
164     return ErrorCode::SUCCESS;
165 }
166 
GetSurfaceBufferColorSpaceType(SurfaceBuffer * sb,CM_ColorSpaceType & type)167 ErrorCode ColorSpaceHelper::GetSurfaceBufferColorSpaceType(SurfaceBuffer *sb, CM_ColorSpaceType &type)
168 {
169     sptr<SurfaceBuffer> buffer = sb;
170     auto res = MetadataHelper::GetColorSpaceType(buffer, type);
171     CHECK_AND_RETURN_RET_LOG(res == GSError::GSERROR_OK, ErrorCode::ERR_GET_COLORSPACETYPE_FAIL,
172         "GetSurfaceBufferColorSpaceType: GetColorSpaceType fail! res=%{public}d", res);
173     return ErrorCode::SUCCESS;
174 }
175 
SetHDRDynamicMetadata(SurfaceBuffer * sb,const std::vector<uint8_t> & hdrDynamicMetadata)176 ErrorCode ColorSpaceHelper::SetHDRDynamicMetadata(SurfaceBuffer *sb, const std::vector<uint8_t> &hdrDynamicMetadata)
177 {
178     sptr<SurfaceBuffer> buffer = sb;
179     auto res = MetadataHelper::SetHDRDynamicMetadata(buffer, hdrDynamicMetadata);
180     CHECK_AND_RETURN_RET_LOG(res == GSError::GSERROR_OK, ErrorCode::ERR_SET_METADATA_FAIL,
181         "SetHDRDynamicMetadata: SetHDRDynamicMetadata fail! res=%{public}d", res);
182     return ErrorCode::SUCCESS;
183 }
184 
SetHDRStaticMetadata(SurfaceBuffer * sb,const std::vector<uint8_t> & hdrStaticMetadata)185 ErrorCode ColorSpaceHelper::SetHDRStaticMetadata(SurfaceBuffer *sb, const std::vector<uint8_t> &hdrStaticMetadata)
186 {
187     sptr<SurfaceBuffer> buffer = sb;
188     auto res = MetadataHelper::SetHDRStaticMetadata(buffer, hdrStaticMetadata);
189     CHECK_AND_RETURN_RET_LOG(res == GSError::GSERROR_OK, ErrorCode::ERR_SET_METADATA_FAIL,
190         "SetHDRStaticMetadata: SetHDRStaticMetadata fail! res=%{public}d", res);
191     return ErrorCode::SUCCESS;
192 }
193 
UpdateMetadata(EffectBuffer * input)194 ErrorCode ColorSpaceHelper::UpdateMetadata(EffectBuffer *input)
195 {
196     CHECK_AND_RETURN_RET_LOG(input != nullptr && input->bufferInfo_ != nullptr && input->extraInfo_ != nullptr,
197         ErrorCode::ERR_INPUT_NULL, "UpdateMetadata: inputBuffer is null");
198 
199     return UpdateMetadata(input->extraInfo_->surfaceBuffer, input->bufferInfo_->colorSpace_);
200 }
201 
UpdateMetadata(SurfaceBuffer * input,const EffectColorSpace & colorSpace)202 ErrorCode ColorSpaceHelper::UpdateMetadata(SurfaceBuffer *input, const EffectColorSpace &colorSpace)
203 {
204     EFFECT_LOGD("UpdateMetadata: colorSpace=%{public}d}", colorSpace);
205     if (input == nullptr || !ColorSpaceHelper::IsHdrColorSpace(colorSpace)) {
206         return ErrorCode::SUCCESS;
207     }
208 
209     std::shared_ptr<MetadataGenerator> metadataGenerator = std::make_shared<MetadataGenerator>();
210     return metadataGenerator->ProcessImage(input);
211 }
212 
ApplyColorSpaceIfNeed(std::shared_ptr<EffectBuffer> & srcBuffer,const std::shared_ptr<EffectContext> & context,EffectColorSpace & colorSpace)213 ErrorCode ApplyColorSpaceIfNeed(std::shared_ptr<EffectBuffer> &srcBuffer, const std::shared_ptr<EffectContext> &context,
214     EffectColorSpace &colorSpace)
215 {
216     if (!ColorSpaceManager::IsNeedConvertColorSpace(colorSpace)) {
217         return ErrorCode::SUCCESS;
218     }
219 
220     EFFECT_LOGD("ColorSpaceHelper::ApplyColorSpace");
221     void *buffer = srcBuffer->buffer_;
222     std::shared_ptr<Memory> memory = context->memoryManager_->GetMemoryByAddr(buffer);
223     EffectColorSpace outputColorSpace = EffectColorSpace::DEFAULT;
224     ErrorCode res = context->colorSpaceManager_->ApplyColorSpace(srcBuffer.get(), colorSpace, outputColorSpace);
225     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
226         "ApplyColorSpaceIfNeed: ConvertColorSpace fail! res=%{public}d, colorSpace=%{public}d", res, colorSpace);
227 
228     // update memoryManager memory
229     if (buffer != srcBuffer->buffer_) {
230         EFFECT_LOGD("ApplyColorSpaceIfNeed: update memory.");
231         context->memoryManager_->RemoveMemory(memory);
232 
233         std::shared_ptr<Memory> updateMemory = std::make_shared<Memory>();
234         updateMemory->memoryData_ = std::make_shared<MemoryData>();
235         updateMemory->memoryData_->data = srcBuffer->buffer_;
236         updateMemory->memoryData_->memoryInfo.bufferInfo = *srcBuffer->bufferInfo_;
237         updateMemory->memoryData_->memoryInfo.extra = srcBuffer->extraInfo_->surfaceBuffer;
238         updateMemory->memoryData_->memoryInfo.bufferType = srcBuffer->extraInfo_->bufferType;
239         updateMemory->memDataType_ = MemDataType::INPUT;
240         updateMemory->isAllowModify_ = true;
241         context->memoryManager_->AddMemory(updateMemory);
242     }
243 
244     colorSpace = outputColorSpace;
245     return ErrorCode::SUCCESS;
246 }
247 
DecomposeHdrImageIfNeed(const EffectColorSpace & colorSpace,const EffectColorSpace & chosenColorSpace,std::shared_ptr<EffectBuffer> & buffer,const std::shared_ptr<EffectContext> & context)248 ErrorCode DecomposeHdrImageIfNeed(const EffectColorSpace &colorSpace, const EffectColorSpace &chosenColorSpace,
249     std::shared_ptr<EffectBuffer> &buffer, const std::shared_ptr<EffectContext> &context)
250 {
251     bool isNeedDecompose =
252         ColorSpaceHelper::IsHdrColorSpace(colorSpace) && !ColorSpaceHelper::IsHdrColorSpace(chosenColorSpace);
253     if (!isNeedDecompose) {
254         return ErrorCode::SUCCESS;
255     }
256 
257     EFFECT_LOGI("ColorSpaceHelper::DecomposeHdrImage");
258     std::shared_ptr<Memory> oldMemory = context->memoryManager_->GetMemoryByAddr(buffer->buffer_);
259     std::shared_ptr<ColorSpaceConverter> converter = std::make_shared<ColorSpaceConverter>();
260     std::shared_ptr<EffectBuffer> sdrImage = nullptr;
261     ErrorCode res = converter->ProcessHdrImage(buffer.get(), sdrImage);
262     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "DecomposeHdrImageIfNeed: ProcessHdrImage fail! "
263         "res=%{public}d, colorSpace=%{public}d, chosenColorSpace=%{public}d", res, colorSpace, chosenColorSpace);
264     CHECK_AND_RETURN_RET_LOG(sdrImage != nullptr && sdrImage->extraInfo_ != nullptr, ErrorCode::ERR_INPUT_NULL,
265         "DecomposeHdrImageIfNeed: sdrImage is null or extraInfo of sdrImage is null!"
266         "sdrImage=%{public}d, sdrImage->extraInfo_=%{public}d", sdrImage == nullptr, sdrImage->extraInfo_ == nullptr);
267 
268     context->memoryManager_->RemoveMemory(oldMemory);
269     std::shared_ptr<MemoryData> memoryData = converter->GetMemoryData(sdrImage->extraInfo_->surfaceBuffer);
270 
271     SurfaceBuffer *sb = sdrImage->extraInfo_->surfaceBuffer;
272     ColorSpaceHelper::SetSurfaceBufferMetadataType(sb, CM_HDR_Metadata_Type::CM_METADATA_NONE);
273     ColorSpaceHelper::SetSurfaceBufferColorSpaceType(sb, CM_ColorSpaceType::CM_COLORSPACE_NONE);
274 
275     std::shared_ptr<Memory> memory = std::make_shared<Memory>();
276     memory->memoryData_ = memoryData;
277     context->memoryManager_->AddMemory(memory);
278     *buffer = *sdrImage;
279 
280     return ErrorCode::SUCCESS;
281 }
282 
ConvertColorSpace(std::shared_ptr<EffectBuffer> & srcBuffer,std::shared_ptr<EffectContext> & context)283 ErrorCode ColorSpaceHelper::ConvertColorSpace(std::shared_ptr<EffectBuffer> &srcBuffer,
284     std::shared_ptr<EffectContext> &context)
285 {
286     EffectColorSpace colorSpace = srcBuffer->bufferInfo_->colorSpace_;
287     EFFECT_LOGD("ConvertColorSpace: colorSpace=%{public}d", colorSpace);
288 
289     // If color space is none, it means that color space is not supported. But it still should return success,
290     // because the real color space maybe defined as ColorSpaceName::CUSTOM in ExtDecoder::getGrColorSpace or
291     // the color space is not exist when invoking InnerGetGrColorSpacePtr of pixelmap returned null ptr.
292     if (colorSpace == EffectColorSpace::DEFAULT) {
293         EFFECT_LOGI("ConvertColorSpace: colorspace is none! Do nothing!");
294         return ErrorCode::SUCCESS;
295     }
296 
297     EFFECT_LOGD("ColorSpaceHelper::ConvertColorSpace colorSpace=%{public}d", colorSpace);
298     ErrorCode res = ApplyColorSpaceIfNeed(srcBuffer, context, colorSpace);
299     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ConvertColorSpace: ConvertColorSpaceIfNeed fail! "
300         "res=%{public}d, colorSpace=%{public}d", res, colorSpace);
301 
302     EffectColorSpace chosenColorSpace = EffectColorSpace::DEFAULT;
303     res = context->colorSpaceManager_->ChooseColorSpace(
304         context->filtersSupportedColorSpace_, colorSpace, chosenColorSpace);
305     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ConvertColorSpace: ChooseColorSpace fail! "
306         "res=%{public}d, colorSpace=%{public}d", res, colorSpace);
307 
308     EFFECT_LOGD("ConvertColorSpace: colorSpace=%{public}d, chosenColorSpace=%{public}d", colorSpace, chosenColorSpace);
309     res = DecomposeHdrImageIfNeed(colorSpace, chosenColorSpace, srcBuffer, context);
310     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ConvertColorSpace: DecomposeHdrImageIfNeed fail! "
311         "res=%{public}d, colorSpace=%{public}d, chosenColorSpace=%{public}d", res, colorSpace, chosenColorSpace);
312 
313     return ErrorCode::SUCCESS;
314 }
315 } // namespace Effect
316 } // namespace Media
317 } // namespace OHOS