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