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