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 "contrast_efilter.h"
17 
18 #include "effect_log.h"
19 #include "efilter_factory.h"
20 #include "json_helper.h"
21 #include "common_utils.h"
22 #include "cpu_contrast_algo.h"
23 #include "gpu_contrast_algo.h"
24 
25 namespace OHOS {
26 namespace Media {
27 namespace Effect {
28 REGISTER_EFILTER_FACTORY(ContrastEFilter, "Contrast");
29 std::shared_ptr<EffectInfo> ContrastEFilter::info_ = nullptr;
30 const float ContrastEFilter::Parameter::INTENSITY_RANGE[] = { -100.f, 100.f };
31 const std::string ContrastEFilter::Parameter::KEY_INTENSITY = "FilterIntensity";
32 
ContrastEFilter(const std::string & name)33 ContrastEFilter::ContrastEFilter(const std::string &name) : EFilter(name)
34 {
35     gpuContrastAlgo_ = std::make_shared<GpuContrastAlgo>();
36     contrastFilterInfo_ = {
37         {
38             IPType::CPU,
39             {
40                 { IEffectFormat::RGBA8888, CpuContrastAlgo::OnApplyRGBA8888 },
41                 { IEffectFormat::YUVNV12, CpuContrastAlgo::OnApplyYUVNV12 },
42                 { IEffectFormat::YUVNV21, CpuContrastAlgo::OnApplyYUVNV21 },
43             }
44         },
45         {
46             IPType::GPU,
47             {
48                 {
49                     IEffectFormat::RGBA8888,
50                     [this](EffectBuffer *src, EffectBuffer *dst, std::map<std::string, Plugin::Any> &value,
51                         std::shared_ptr<EffectContext> &context)
52                         { return gpuContrastAlgo_->OnApplyRGBA8888(src, dst, value, context); }
53                 },
54             }
55         }
56     };
57 }
58 
~ContrastEFilter()59 ContrastEFilter::~ContrastEFilter()
60 {
61     gpuContrastAlgo_->Release();
62 }
63 
Render(EffectBuffer * buffer,std::shared_ptr<EffectContext> & context)64 ErrorCode ContrastEFilter::Render(EffectBuffer *buffer, std::shared_ptr<EffectContext> &context)
65 {
66     if (context->ipType_ == IPType::GPU) {
67         std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
68         std::shared_ptr<ExtraInfo> extraInfo = std::make_shared<ExtraInfo>();
69         extraInfo->dataType = DataType::TEX;
70         std::shared_ptr<EffectBuffer> effectBuffer = std::make_shared<EffectBuffer>(bufferInfo, nullptr, extraInfo);
71         ErrorCode res = Render(buffer, effectBuffer.get(), context);
72         CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "filter(%{public}s) render fail", name_.c_str());
73         return PushData(effectBuffer.get(), context);
74     }
75     ErrorCode res = Render(buffer, buffer, context);
76     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "filter(%{public}s) render fail", name_.c_str());
77     return PushData(buffer, context);
78 }
79 
Render(EffectBuffer * src,EffectBuffer * dst,std::shared_ptr<EffectContext> & context)80 ErrorCode ContrastEFilter::Render(EffectBuffer *src, EffectBuffer *dst, std::shared_ptr<EffectContext> &context)
81 {
82     IPType ipType = context->ipType_;
83     auto it = contrastFilterInfo_.find(ipType);
84     CHECK_AND_RETURN_RET_LOG(it != contrastFilterInfo_.end(), ErrorCode::ERR_UNSUPPORTED_IPTYPE_FOR_EFFECT,
85         "ipType=%{public}d is not support! filter=%{public}s", ipType, name_.c_str());
86 
87     IEffectFormat formatType = src->bufferInfo_->formatType_;
88     std::unordered_map<IEffectFormat, ApplyFunc> formatFuncs = it->second;
89     auto formatIter = formatFuncs.find(formatType);
90     CHECK_AND_RETURN_RET_LOG(formatIter != formatFuncs.end(), ErrorCode::ERR_UNSUPPORTED_FORMAT_TYPE,
91         "format=%{public}d is not support! filter=%{public}s", formatType, name_.c_str());
92 
93     return formatIter->second(src, dst, values_, context);
94 }
95 
SetValue(const std::string & key,Plugin::Any & value)96 ErrorCode ContrastEFilter::SetValue(const std::string &key, Plugin::Any &value)
97 {
98     if (Parameter::KEY_INTENSITY.compare(key) != 0) {
99         EFFECT_LOGE("key is not support! key=%{public}s", key.c_str());
100         return ErrorCode::ERR_UNSUPPORTED_VALUE_KEY;
101     }
102 
103     auto contrastPtr = Plugin::AnyCast<float>(&value);
104     if (contrastPtr == nullptr) {
105         EFFECT_LOGE("the type is not float! key=%{public}s", key.c_str());
106         return ErrorCode::ERR_ANY_CAST_TYPE_NOT_FLOAT;
107     }
108 
109     float contrast = *contrastPtr;
110     if (contrast < Parameter::INTENSITY_RANGE[0] || contrast > Parameter::INTENSITY_RANGE[1]) {
111         EFFECT_LOGW("the value is out of range! key=%{public}s, value=%{public}f, range=[%{public}f, %{public}f]",
112             key.c_str(), contrast, Parameter::INTENSITY_RANGE[0], Parameter::INTENSITY_RANGE[1]);
113         *contrastPtr = CommonUtils::Clip(contrast, Parameter::INTENSITY_RANGE[0], Parameter::INTENSITY_RANGE[1]);
114     }
115 
116     return EFilter::SetValue(key, value);
117 }
118 
Restore(const EffectJsonPtr & values)119 ErrorCode ContrastEFilter::Restore(const EffectJsonPtr &values)
120 {
121     // If the developer does not set parameters, the function returns a failure, but it is a normal case.
122     if (!values->HasElement(Parameter::KEY_INTENSITY)) {
123         EFFECT_LOGW("not set value! key=%{public}s", Parameter::KEY_INTENSITY.c_str());
124         return ErrorCode::SUCCESS;
125     }
126 
127     float contrast = values->GetFloat(Parameter::KEY_INTENSITY);
128     if (contrast < Parameter::INTENSITY_RANGE[0] || contrast > Parameter::INTENSITY_RANGE[1]) {
129         return ErrorCode::ERR_VALUE_OUT_OF_RANGE;
130     }
131     Plugin::Any any = contrast;
132     return SetValue(Parameter::KEY_INTENSITY, any);
133 }
134 
GetEffectInfo(const std::string & name)135 std::shared_ptr<EffectInfo> ContrastEFilter::GetEffectInfo(const std::string &name)
136 {
137     if (info_ != nullptr) {
138         return info_;
139     }
140     info_ = std::make_unique<EffectInfo>();
141     info_->formats_.emplace(IEffectFormat::RGBA8888, std::vector<IPType>{ IPType::CPU, IPType::GPU });
142     info_->formats_.emplace(IEffectFormat::YUVNV21, std::vector<IPType>{ IPType::CPU });
143     info_->formats_.emplace(IEffectFormat::YUVNV12, std::vector<IPType>{ IPType::CPU });
144     info_->category_ = Category::COLOR_ADJUST;
145     info_->colorSpaces_ = {
146         EffectColorSpace::SRGB,
147         EffectColorSpace::SRGB_LIMIT,
148         EffectColorSpace::DISPLAY_P3,
149         EffectColorSpace::DISPLAY_P3_LIMIT
150     };
151     return info_;
152 }
153 
PreRender(IEffectFormat & format)154 ErrorCode ContrastEFilter::PreRender(IEffectFormat &format)
155 {
156     return ErrorCode::SUCCESS;
157 }
158 } // namespace Effect
159 } // namespace Media
160 } // namespace OHOS