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_strategy.h"
17
18 #include <unordered_map>
19
20 #include "effect_log.h"
21 #include "colorspace_helper.h"
22
23 namespace OHOS {
24 namespace Media {
25 namespace Effect {
26
27 static const std::unordered_map<EffectColorSpace, EffectColorSpace> COLORSPACE_CONVERTER_MAP = {
28 { EffectColorSpace::SRGB, EffectColorSpace::SRGB },
29 { EffectColorSpace::SRGB_LIMIT, EffectColorSpace::SRGB_LIMIT },
30 { EffectColorSpace::DISPLAY_P3, EffectColorSpace::DISPLAY_P3 },
31 { EffectColorSpace::DISPLAY_P3_LIMIT, EffectColorSpace::DISPLAY_P3_LIMIT },
32 { EffectColorSpace::BT2020_HLG, EffectColorSpace::BT2020_HLG },
33 { EffectColorSpace::BT2020_HLG_LIMIT, EffectColorSpace::BT2020_HLG_LIMIT },
34 { EffectColorSpace::BT2020_PQ, EffectColorSpace::BT2020_PQ },
35 { EffectColorSpace::BT2020_PQ_LIMIT, EffectColorSpace::BT2020_PQ_LIMIT },
36 { EffectColorSpace::ADOBE_RGB, EffectColorSpace::DISPLAY_P3 },
37 };
38
39 static const std::unordered_map<EffectColorSpace, EffectColorSpace> COLORSPACE_HDR_CONVERTER_MAP = {
40 { EffectColorSpace::BT2020_HLG, EffectColorSpace::DISPLAY_P3 },
41 { EffectColorSpace::BT2020_HLG_LIMIT, EffectColorSpace::DISPLAY_P3_LIMIT },
42 { EffectColorSpace::BT2020_PQ, EffectColorSpace::DISPLAY_P3 },
43 { EffectColorSpace::BT2020_PQ_LIMIT, EffectColorSpace::DISPLAY_P3_LIMIT },
44 };
45
46 static const std::vector<EffectColorSpace> DEFAULT_SUPPORTED_COLORSPACE = {
47 EffectColorSpace::SRGB,
48 EffectColorSpace::SRGB_LIMIT,
49 EffectColorSpace::DISPLAY_P3,
50 EffectColorSpace::DISPLAY_P3_LIMIT
51 };
52
IsSupportedColorSpace(EffectColorSpace colorSpace)53 bool ColorSpaceStrategy::IsSupportedColorSpace(EffectColorSpace colorSpace)
54 {
55 for (const auto &it : COLORSPACE_CONVERTER_MAP) {
56 if (it.first == colorSpace) {
57 return true;
58 }
59 }
60 return false;
61 }
62
IsNeedConvertColorSpace(EffectColorSpace colorSpace)63 bool ColorSpaceStrategy::IsNeedConvertColorSpace(EffectColorSpace colorSpace)
64 {
65 EffectColorSpace converterColorSpace = EffectColorSpace::DEFAULT;
66 for (const auto &it : COLORSPACE_CONVERTER_MAP) {
67 if (it.first == colorSpace) {
68 converterColorSpace = it.second;
69 break;
70 }
71 }
72 return colorSpace != converterColorSpace;
73 }
74
GetTargetColorSpace(EffectColorSpace src)75 EffectColorSpace ColorSpaceStrategy::GetTargetColorSpace(EffectColorSpace src)
76 {
77 auto it = COLORSPACE_CONVERTER_MAP.find(src);
78 return it == COLORSPACE_CONVERTER_MAP.end() ? EffectColorSpace::DEFAULT : it->second;
79 }
80
GetAllSupportedColorSpaces()81 std::unordered_set<EffectColorSpace> ColorSpaceStrategy::GetAllSupportedColorSpaces()
82 {
83 std::unordered_set<EffectColorSpace> supportedColorSpace;
84 for (const auto &it : COLORSPACE_CONVERTER_MAP) {
85 supportedColorSpace.emplace(it.second);
86 }
87
88 return supportedColorSpace;
89 }
90
Init(const std::shared_ptr<EffectBuffer> & src,const std::shared_ptr<EffectBuffer> & dst)91 void ColorSpaceStrategy::Init(const std::shared_ptr<EffectBuffer> &src, const std::shared_ptr<EffectBuffer> &dst)
92 {
93 src_ = src;
94 dst_ = dst;
95 }
96
ChooseColorSpaceInner(const EffectColorSpace & srcRealColorSpace,const std::unordered_set<EffectColorSpace> & filtersSupportedColorSpace,EffectColorSpace & outputColorSpace)97 ErrorCode ChooseColorSpaceInner(const EffectColorSpace &srcRealColorSpace,
98 const std::unordered_set<EffectColorSpace> &filtersSupportedColorSpace, EffectColorSpace &outputColorSpace)
99 {
100 if (filtersSupportedColorSpace.find(srcRealColorSpace) != filtersSupportedColorSpace.end()) {
101 outputColorSpace = srcRealColorSpace;
102 return ErrorCode::SUCCESS;
103 }
104
105 if (std::find(DEFAULT_SUPPORTED_COLORSPACE.begin(), DEFAULT_SUPPORTED_COLORSPACE.end(), srcRealColorSpace) !=
106 DEFAULT_SUPPORTED_COLORSPACE.end()) {
107 outputColorSpace = srcRealColorSpace;
108 return ErrorCode::SUCCESS;
109 }
110
111 auto it = COLORSPACE_HDR_CONVERTER_MAP.find(srcRealColorSpace);
112 if (it == COLORSPACE_HDR_CONVERTER_MAP.end()) {
113 EFFECT_LOGE("ChooseColorSpaceInner: colorSpace[%{public}d] not support convert.", srcRealColorSpace);
114 return ErrorCode::ERR_COLORSPACE_NOT_SUPPORT_CONVERT;
115 }
116
117 outputColorSpace = it->second;
118 return ErrorCode::SUCCESS;
119 }
120
ChooseColorSpaceWithOutput(const EffectColorSpace & srcRealColorSpace,EffectBuffer * src,EffectBuffer * dst,const std::unordered_set<EffectColorSpace> & filtersSupportedColorSpace,EffectColorSpace & outputColorSpace)121 ErrorCode ChooseColorSpaceWithOutput(const EffectColorSpace &srcRealColorSpace, EffectBuffer *src, EffectBuffer *dst,
122 const std::unordered_set<EffectColorSpace> &filtersSupportedColorSpace, EffectColorSpace &outputColorSpace)
123 {
124 const std::shared_ptr<BufferInfo> &dstBufferInfo = dst->bufferInfo_;
125 CHECK_AND_RETURN_RET_LOG(dstBufferInfo != nullptr, ErrorCode::ERR_INPUT_NULL,
126 "ChooseColorSpaceWithOutput: dstBufferInfo is null!");
127
128 EffectColorSpace chooseColorSpace = EffectColorSpace::DEFAULT;
129 ErrorCode res = ChooseColorSpaceInner(srcRealColorSpace, filtersSupportedColorSpace, chooseColorSpace);
130 CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ChooseColorSpaceWithOutput: ChooseColorSpaceInner fail!");
131
132 if (src->extraInfo_->dataType == DataType::PIXEL_MAP && dst->extraInfo_->dataType == DataType::PIXEL_MAP) {
133 // color space is same.
134 bool isSrcHdr = ColorSpaceHelper::IsHdrColorSpace(srcRealColorSpace);
135 bool isChoseHdr = ColorSpaceHelper::IsHdrColorSpace(chooseColorSpace);
136 CHECK_AND_RETURN_RET_LOG(isSrcHdr == isChoseHdr, ErrorCode::ERR_NOT_SUPPORT_INPUT_OUTPUT_COLORSPACE,
137 "ChooseColorSpaceWithOutput: input and output color space not same! "
138 "srcRealColorSpace=%{public}d, chooseColorSpace=%{public}d", srcRealColorSpace, chooseColorSpace);
139 }
140
141 outputColorSpace = chooseColorSpace;
142 return ErrorCode::SUCCESS;
143 }
144
ChooseColorSpaceWithoutOutput(const EffectColorSpace & srcRealColorSpace,const std::unordered_set<EffectColorSpace> & filtersSupportedColorSpace,EffectColorSpace & outputColorSpace)145 ErrorCode ChooseColorSpaceWithoutOutput(const EffectColorSpace &srcRealColorSpace,
146 const std::unordered_set<EffectColorSpace> &filtersSupportedColorSpace, EffectColorSpace &outputColorSpace)
147 {
148 return ChooseColorSpaceInner(srcRealColorSpace, filtersSupportedColorSpace, outputColorSpace);
149 }
150
ChooseColorSpace(const std::unordered_set<EffectColorSpace> & filtersSupportedColorSpace,const EffectColorSpace & srcRealColorSpace,EffectColorSpace & outputColorSpace)151 ErrorCode ColorSpaceStrategy::ChooseColorSpace(const std::unordered_set<EffectColorSpace> &filtersSupportedColorSpace,
152 const EffectColorSpace &srcRealColorSpace, EffectColorSpace &outputColorSpace)
153 {
154 CHECK_AND_RETURN_RET_LOG(src_ != nullptr, ErrorCode::ERR_INPUT_NULL, "ChooseColorSpace: src_ is null!");
155
156 if (dst_ == nullptr || dst_->buffer_ == src_->buffer_) {
157 return ChooseColorSpaceWithoutOutput(srcRealColorSpace, filtersSupportedColorSpace, outputColorSpace);
158 }
159 return ChooseColorSpaceWithOutput(srcRealColorSpace, src_.get(), dst_.get(), filtersSupportedColorSpace,
160 outputColorSpace);
161 }
162
CheckConverterColorSpace(const EffectColorSpace & targetColorSpace)163 ErrorCode ColorSpaceStrategy::CheckConverterColorSpace(const EffectColorSpace &targetColorSpace)
164 {
165 CHECK_AND_RETURN_RET_LOG(src_ != nullptr, ErrorCode::ERR_PARAM_INVALID,
166 "GetConverterEffectBuffer: src_ is null!");
167
168 // only input data
169 if (dst_ == nullptr || dst_->buffer_ == src_->buffer_) {
170 return ErrorCode::SUCCESS;
171 }
172
173 DataType dataType = dst_->extraInfo_->dataType;
174 if (dataType == DataType::NATIVE_WINDOW) {
175 return ErrorCode::SUCCESS;
176 }
177
178 // check color space is match or not.
179 const std::shared_ptr<BufferInfo> &srcBufferInfo = src_->bufferInfo_;
180 const std::shared_ptr<BufferInfo> &dstBufferInfo = dst_->bufferInfo_;
181 CHECK_AND_RETURN_RET_LOG(srcBufferInfo != nullptr && dstBufferInfo != nullptr, ErrorCode::ERR_PARAM_INVALID,
182 "CheckConverterColorSpace: srcBufferInfo or dstBufferInfo is null!");
183 EffectColorSpace srcColorSpace = srcBufferInfo->colorSpace_;
184 EffectColorSpace dstColorSpace = dstBufferInfo->colorSpace_;
185 CHECK_AND_RETURN_RET_LOG(targetColorSpace == dstColorSpace, ErrorCode::ERR_NOT_SUPPORT_INPUT_OUTPUT_COLORSPACE,
186 "CheckConverterColorSpace: colorspace not match! target=%{public}d, src=%{public}d, dst=%{public}d",
187 targetColorSpace, srcColorSpace, dstColorSpace);
188
189 return ErrorCode::SUCCESS;
190 }
191
Deinit()192 void ColorSpaceStrategy::Deinit()
193 {
194 src_ = nullptr;
195 dst_ = nullptr;
196 }
197
198 } // namespace Effect
199 } // namespace Media
200 } // namespace OHOS