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 "gtest/gtest.h"
17 
18 #include "image_effect_inner.h"
19 #include "efilter_factory.h"
20 #include "mock_pixel_map.h"
21 #include "brightness_efilter.h"
22 #include "contrast_efilter.h"
23 #include "test_common.h"
24 #include "external_loader.h"
25 #include "crop_efilter.h"
26 #include "mock_producer_surface.h"
27 
28 using namespace testing::ext;
29 using namespace OHOS::Media::Effect;
30 
31 static std::string g_jpgPath;
32 static std::string g_notJpgPath;
33 static std::string g_jpgUri;
34 static std::string g_notJpgUri;
35 
36 namespace OHOS {
37 namespace Media {
38 namespace Effect {
39 namespace Test {
40 class CustomTestEFilter : public IFilterDelegate {
41 public:
Render(void * efilter,EffectBuffer * src,EffectBuffer * dst,std::shared_ptr<EffectContext> & context)42     bool Render(void *efilter, EffectBuffer *src, EffectBuffer *dst, std::shared_ptr<EffectContext> &context) override
43     {
44         return true;
45     }
46 
Render(void * efilter,EffectBuffer * src,std::shared_ptr<EffectContext> & context)47     bool Render(void *efilter, EffectBuffer *src, std::shared_ptr<EffectContext> &context) override
48     {
49         return true;
50     }
51 
SetValue(void * efilter,const std::string & key,const Plugin::Any & value)52     bool SetValue(void *efilter, const std::string &key, const Plugin::Any &value) override
53     {
54         return true;
55     }
56 
Save(void * efilter,EffectJsonPtr & res)57     bool Save(void *efilter, EffectJsonPtr &res) override
58     {
59         auto *filter = static_cast<EFilter *>(efilter);
60         return filter != nullptr && filter->Save(res) == ErrorCode::SUCCESS;
61     }
62 
Restore(const EffectJsonPtr & values)63     void *Restore(const EffectJsonPtr &values) override
64     {
65         filter_ = EFilterFactory::Instance()->Create(CUSTOM_TEST_EFILTER);
66         Plugin::Any brightness = values->GetFloat("brightness");
67         filter_->SetValue("brightness", brightness);
68         return filter_.get();
69     }
70 
GetEffectInfo()71     void *GetEffectInfo() override
72     {
73         if (info_ != nullptr) {
74             return &info_;
75         }
76         info_ = std::make_unique<EffectInfo>();
77         info_->formats_.emplace(IEffectFormat::RGBA8888, std::vector<IPType>{ IPType::CPU });
78         info_->category_ = Category::SHAPE_ADJUST;
79         return &info_;
80     }
81 private:
82     static std::shared_ptr<EffectInfo> info_;
83     std::shared_ptr<EFilter> filter_;
84 };
85 std::shared_ptr<EffectInfo> CustomTestEFilter::info_ = nullptr;
86 
87 class TestImageEffect : public testing::Test {
88 public:
89     TestImageEffect() = default;
90 
91     ~TestImageEffect() override = default;
92 
SetUpTestCase()93     static void SetUpTestCase()
94     {
95         g_jpgPath = std::string("/data/test/resource/image_effect_test1.jpg");
96         g_notJpgPath = std::string("/data/test/resource/image_effect_test2.png");
97         g_jpgUri = std::string("file:///data/test/resource/image_effect_test1.jpg");
98         g_notJpgUri = std::string("file:///data/test/resource/image_effect_test2.png");
99     }
100 
TearDownTestCase()101     static void TearDownTestCase() {}
102 
SetUp()103     void SetUp() override
104     {
105         mockPixelMap_ = new MockPixelMap();
106         imageEffect_ = new ImageEffect();
107         ExternLoader::Instance()->InitExt();
108         EFilterFactory::Instance()->functions_.clear();
109         EFilterFactory::Instance()->RegisterEFilter<BrightnessEFilter>(BRIGHTNESS_EFILTER);
110         EFilterFactory::Instance()->RegisterEFilter<ContrastEFilter>(CONTRAST_EFILTER);
111         EFilterFactory::Instance()->RegisterEFilter<CropEFilter>(CROP_EFILTER);
112     }
113 
TearDown()114     void TearDown() override
115     {
116         delete mockPixelMap_;
117         mockPixelMap_ = nullptr;
118         delete imageEffect_;
119         imageEffect_ = nullptr;
120     }
121     PixelMap *mockPixelMap_ = nullptr;
122     ImageEffect *imageEffect_ = nullptr;
123 };
124 
125 HWTEST_F(TestImageEffect, AddEfilter001, TestSize.Level1)
126 {
127     std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
128     std::shared_ptr<EFilter> brightnessEFilter = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
129     imageEffect->AddEFilter(brightnessEFilter);
130     ASSERT_EQ(imageEffect->efilters_.size(), 1);
131     ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter);
132 
133     std::shared_ptr<EFilter> cropEFilter1 = EFilterFactory::Instance()->Create(CROP_EFILTER);
134     imageEffect->AddEFilter(cropEFilter1);
135     ASSERT_EQ(imageEffect->efilters_.size(), 2);
136     ASSERT_EQ(imageEffect->efilters_.at(0), cropEFilter1);
137     ASSERT_EQ(imageEffect->efilters_.at(1), brightnessEFilter);
138 
139     std::shared_ptr<EFilter> cropEFilter2 = EFilterFactory::Instance()->Create(CROP_EFILTER);
140     imageEffect->AddEFilter(cropEFilter2);
141     ASSERT_EQ(imageEffect->efilters_.size(), 3);
142     ASSERT_EQ(imageEffect->efilters_.at(0), cropEFilter1);
143     ASSERT_EQ(imageEffect->efilters_.at(1), cropEFilter2);
144     ASSERT_EQ(imageEffect->efilters_.at(2), brightnessEFilter);
145 }
146 
147 HWTEST_F(TestImageEffect, Start001, TestSize.Level1)
148 {
149     std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
150     std::shared_ptr<EFilter> efilter = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
151     Plugin::Any value = 100.f;
152     ErrorCode result = efilter->SetValue(KEY_FILTER_INTENSITY, value);
153     ASSERT_EQ(result, ErrorCode::SUCCESS);
154     imageEffect->AddEFilter(efilter);
155     result = imageEffect->SetInputPixelMap(mockPixelMap_);
156     ASSERT_EQ(result, ErrorCode::SUCCESS);
157     result = imageEffect->SetOutputPixelMap(mockPixelMap_);
158     ASSERT_EQ(result, ErrorCode::SUCCESS);
159     result = imageEffect->Start();
160     ASSERT_EQ(result, ErrorCode::SUCCESS);
161 }
162 
163 HWTEST_F(TestImageEffect, InsertEfilter001, TestSize.Level1)
164 {
165     std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
166     std::shared_ptr<EFilter> brightnessEFilter1 = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
167     imageEffect->InsertEFilter(brightnessEFilter1, 0);
168     ASSERT_EQ(imageEffect->efilters_.size(), 1);
169     ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter1);
170 
171     std::shared_ptr<EFilter> contrastEFilter = EFilterFactory::Instance()->Create(CONTRAST_EFILTER);
172     imageEffect->AddEFilter(contrastEFilter);
173     ASSERT_EQ(imageEffect->efilters_.size(), 2);
174     ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter1);
175     ASSERT_EQ(imageEffect->efilters_.at(1), contrastEFilter);
176 
177     std::shared_ptr<EFilter> brightnessEFilter2 = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
178     imageEffect->InsertEFilter(brightnessEFilter2, 1);
179     ASSERT_EQ(imageEffect->efilters_.size(), 3);
180     ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter1);
181     ASSERT_EQ(imageEffect->efilters_.at(1), brightnessEFilter2);
182     ASSERT_EQ(imageEffect->efilters_.at(2), contrastEFilter);
183 }
184 
185 HWTEST_F(TestImageEffect, InsertEfilter002, TestSize.Level1)
186 {
187     std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
188     std::shared_ptr<EFilter> brightnessEFilter1 = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
189     ErrorCode result = imageEffect->InsertEFilter(brightnessEFilter1, 1);
190     ASSERT_NE(result, ErrorCode::SUCCESS);
191 }
192 
193 /**
194  * Feature: ImageEffect
195  * Function: Test ImageEffect::SetInputPath with normal param
196  * SubFunction: NA
197  * FunctionPoints: NA
198  * EnvConditions: NA
199  * CaseDescription: Test ImageEffect::SetInputPath with normal param
200  */
201 HWTEST_F(TestImageEffect, SetInputPath001, TestSize.Level1)
202 {
203     ErrorCode result = imageEffect_->SetInputPath(g_jpgPath);
204     ASSERT_EQ(result, ErrorCode::SUCCESS);
205 }
206 
207 /**
208  * Feature: ImageEffect
209  * Function: Test ImageEffect::SetInputPath with nullptr param
210  * SubFunction: NA
211  * FunctionPoints: NA
212  * EnvConditions: NA
213  * CaseDescription: Test ImageEffect::SetInputPath with nullptr param
214  */
215 HWTEST_F(TestImageEffect, SetInputPath002, TestSize.Level1)
216 {
217     ErrorCode result = imageEffect_->SetInputPath(nullptr);
218     ASSERT_NE(result, ErrorCode::SUCCESS);
219 }
220 
221 /**
222  * Feature: ImageEffect
223  * Function: Test ImageEffect::SetInputPath with not support type param
224  * SubFunction: NA
225  * FunctionPoints: NA
226  * EnvConditions: NA
227  * CaseDescription: Test ImageEffect::SetInputPath with not support type param
228  */
229 HWTEST_F(TestImageEffect, SetInputPath003, TestSize.Level1)
230 {
231     ErrorCode result = imageEffect_->SetInputPath(g_notJpgPath);
232     ASSERT_NE(result, ErrorCode::SUCCESS);
233 }
234 
235 /**
236  * Feature: ImageEffect
237  * Function: Test ImageEffect::SetOutputPath with normal param
238  * SubFunction: NA
239  * FunctionPoints: NA
240  * EnvConditions: NA
241  * CaseDescription: Test ImageEffect::SetOutputPath with normal param
242  */
243 HWTEST_F(TestImageEffect, SetOutputPath001, TestSize.Level1)
244 {
245     ErrorCode result = imageEffect_->SetOutputPath(g_jpgPath);
246     ASSERT_EQ(result, ErrorCode::SUCCESS);
247 }
248 
249 /**
250  * Feature: ImageEffect
251  * Function: Test ImageEffect::SetOutputPath with nullptr param
252  * SubFunction: NA
253  * FunctionPoints: NA
254  * EnvConditions: NA
255  * CaseDescription: Test ImageEffect::SetOutputPath with nullptr param
256  */
257 HWTEST_F(TestImageEffect, SetOutputPath002, TestSize.Level1)
258 {
259     ErrorCode result = imageEffect_->SetOutputPath(nullptr);
260     ASSERT_EQ(result, ErrorCode::SUCCESS);
261 }
262 
263 /**
264  * Feature: ImageEffect
265  * Function: Test ImageEffect::SetOutputPath with not support type param
266  * SubFunction: NA
267  * FunctionPoints: NA
268  * EnvConditions: NA
269  * CaseDescription: Test ImageEffect::SetOutputPath with not support type param
270  */
271 HWTEST_F(TestImageEffect, SetOutputPath003, TestSize.Level1)
272 {
273     ErrorCode result = imageEffect_->SetOutputPath(g_notJpgPath);
274     ASSERT_NE(result, ErrorCode::SUCCESS);
275 }
276 
277 /**
278  * Feature: ImageEffect
279  * Function: Test ImageEffect::SetInputUri with normal param
280  * SubFunction: NA
281  * FunctionPoints: NA
282  * EnvConditions: NA
283  * CaseDescription: Test ImageEffect::SetInputUri with normal param
284  */
285 HWTEST_F(TestImageEffect, SetInputUri001, TestSize.Level1)
286 {
287     ErrorCode result = imageEffect_->SetInputUri(g_jpgUri);
288     ASSERT_EQ(result, ErrorCode::SUCCESS);
289 }
290 
291 /**
292  * Feature: ImageEffect
293  * Function: Test ImageEffect::SetInputUri with nullptr param
294  * SubFunction: NA
295  * FunctionPoints: NA
296  * EnvConditions: NA
297  * CaseDescription: Test ImageEffect::SetInputUri with nullptr param
298  */
299 HWTEST_F(TestImageEffect, SetInputUri002, TestSize.Level1)
300 {
301     ErrorCode result = imageEffect_->SetInputUri(nullptr);
302     ASSERT_NE(result, ErrorCode::SUCCESS);
303 }
304 
305 /**
306  * Feature: ImageEffect
307  * Function: Test ImageEffect::SetInputUri with not support type param
308  * SubFunction: NA
309  * FunctionPoints: NA
310  * EnvConditions: NA
311  * CaseDescription: Test ImageEffect::SetInputUri with not support type param
312  */
313 HWTEST_F(TestImageEffect, SetInputUri003, TestSize.Level1)
314 {
315     ErrorCode result = imageEffect_->SetInputUri(g_notJpgUri);
316     ASSERT_NE(result, ErrorCode::SUCCESS);
317 }
318 
319 /**
320  * Feature: ImageEffect
321  * Function: Test ImageEffect::SetOutputUri with normal param
322  * SubFunction: NA
323  * FunctionPoints: NA
324  * EnvConditions: NA
325  * CaseDescription: Test ImageEffect::SetOutputUri with normal param
326  */
327 HWTEST_F(TestImageEffect, SetOutputUri001, TestSize.Level1)
328 {
329     ErrorCode result = imageEffect_->SetOutputUri(g_jpgUri);
330     ASSERT_EQ(result, ErrorCode::SUCCESS);
331 }
332 
333 /**
334  * Feature: ImageEffect
335  * Function: Test ImageEffect::SetOutputUri with nullptr param
336  * SubFunction: NA
337  * FunctionPoints: NA
338  * EnvConditions: NA
339  * CaseDescription: Test ImageEffect::SetOutputUri with nullptr param
340  */
341 HWTEST_F(TestImageEffect, SetOutputUri002, TestSize.Level1)
342 {
343     ErrorCode result = imageEffect_->SetOutputUri(nullptr);
344     ASSERT_EQ(result, ErrorCode::SUCCESS);
345 }
346 
347 /**
348  * Feature: ImageEffect
349  * Function: Test ImageEffect::SetOutputUri with not support type param
350  * SubFunction: NA
351  * FunctionPoints: NA
352  * EnvConditions: NA
353  * CaseDescription: Test ImageEffect::SetOutputUri with not support type param
354  */
355 HWTEST_F(TestImageEffect, SetOutputUri003, TestSize.Level1)
356 {
357     ErrorCode result = imageEffect_->SetOutputUri(g_notJpgUri);
358     ASSERT_NE(result, ErrorCode::SUCCESS);
359 }
360 
361 HWTEST_F(TestImageEffect, Restore001, TestSize.Level1)
362 {
363     std::string info = "{\"imageEffect\":{\"filters\":[{\"name\":\"Brightness\",\"values\":{\"FilterIntensity\":"
364         "100.0}},{\"name\":\"Contrast\",\"values\":{\"FilterIntensity\":50.0}}],\"name\":\"imageEdit\"}}";
365     std::shared_ptr<ImageEffect> imageEffect = ImageEffect::Restore(info);
366     ASSERT_NE(imageEffect, nullptr);
367     std::vector<std::shared_ptr<EFilter>> efilters = imageEffect->GetEFilters();
368     ASSERT_EQ(efilters.size(), 2);
369     ASSERT_STREQ(efilters.at(0)->GetName().c_str(), BRIGHTNESS_EFILTER);
370     Plugin::Any value;
371     ASSERT_EQ(efilters.at(0)->GetValue(KEY_FILTER_INTENSITY, value), ErrorCode::SUCCESS);
372     auto brightnessRatio = Plugin::AnyCast<float>(&value);
373     ASSERT_NE(brightnessRatio, nullptr);
374     ASSERT_FLOAT_EQ(*brightnessRatio, 100.f);
375 
376     Plugin::Any any;
377     ASSERT_STREQ(efilters.at(1)->GetName().c_str(), CONTRAST_EFILTER);
378     ASSERT_EQ(efilters.at(1)->GetValue(KEY_FILTER_INTENSITY, any), ErrorCode::SUCCESS);
379     auto contrastRatio = Plugin::AnyCast<float>(&any);
380     ASSERT_NE(contrastRatio, nullptr);
381     ASSERT_FLOAT_EQ(*contrastRatio, 50.f);
382 }
383 
384 HWTEST_F(TestImageEffect, Restore002, TestSize.Level1)
385 {
386     std::shared_ptr<IFilterDelegate> customTestEFilter = std::make_unique<CustomTestEFilter>();
387     auto *effectInfo = static_cast<std::shared_ptr<EffectInfo> *>(customTestEFilter->GetEffectInfo());
388     ASSERT_NE(effectInfo, nullptr);
389     EFilterFactory::Instance()->RegisterDelegate(CUSTOM_TEST_EFILTER, customTestEFilter, *effectInfo);
390 
391     std::string info = "{\"imageEffect\":{\"filters\":[{\"name\":\"CustomTestEFilter\",\"values\":{\"brightness\":"
392         "60.0}},{\"name\":\"Contrast\",\"values\":{\"FilterIntensity\":50.0}}],\"name\":\"imageEdit\"}}";
393 
394     std::shared_ptr<ImageEffect> imageEffect = ImageEffect::Restore(info);
395     ASSERT_NE(imageEffect, nullptr);
396     std::vector<std::shared_ptr<EFilter>> efilters = imageEffect->GetEFilters();
397     ASSERT_EQ(efilters.size(), 2);
398     ASSERT_STREQ(efilters.at(0)->GetName().c_str(), "CustomTestEFilter");
399     Plugin::Any value;
400     ASSERT_EQ(efilters.at(0)->GetValue("brightness", value), ErrorCode::SUCCESS);
401     auto brightness = Plugin::AnyCast<float>(&value);
402     ASSERT_NE(brightness, nullptr);
403     ASSERT_FLOAT_EQ(*brightness, 60.f);
404 
405     ErrorCode errorCode = imageEffect->SetInputPixelMap(mockPixelMap_);
406     ASSERT_EQ(errorCode, ErrorCode::SUCCESS);
407     errorCode = imageEffect->Start();
408     ASSERT_EQ(errorCode, ErrorCode::SUCCESS);
409 }
410 
411 HWTEST_F(TestImageEffect, Restore003, TestSize.Level1)
412 {
413     std::string info = "{\"imageEffect\":{\"filters\":[{\"name\":\"Crop\"}],\"name\":\"imageEdit\"}}";
414     std::shared_ptr<ImageEffect> imageEffect = ImageEffect::Restore(info);
415     ASSERT_NE(imageEffect, nullptr);
416     std::vector<std::shared_ptr<EFilter>> efilters = imageEffect->GetEFilters();
417     ASSERT_EQ(efilters.size(), 1);
418     ASSERT_STREQ(efilters.at(0)->GetName().c_str(), CROP_EFILTER);
419 }
420 
421 HWTEST_F(TestImageEffect, Surface001, TestSize.Level1)
422 {
423     sptr<Surface> consumerSurface = Surface::CreateSurfaceAsConsumer("UnitTest");
424     sptr<IBufferProducer> producer = consumerSurface->GetProducer();
425     sptr<ProducerSurface> surf = new(std::nothrow) MockProducerSurface(producer);
426     surf->Init();
427     sptr<Surface> outputSurface = surf;
428 
429     ErrorCode result = imageEffect_->SetOutputSurface(outputSurface);
430     ASSERT_EQ(result, ErrorCode::SUCCESS);
431 
432     sptr<Surface> inputSurface = imageEffect_->GetInputSurface();
433     ASSERT_NE(inputSurface, nullptr);
434 
435     sptr<SurfaceBuffer> surfaceBuffer;
436     sptr<SurfaceBuffer> outBuffer;
437     MockProducerSurface::AllocDmaMemory(surfaceBuffer);
438     OHOS::Rect damages;
439     int64_t timeStamp = 0;
440 
441     // running without filter
442     imageEffect_->ConsumerBufferAvailable(surfaceBuffer, outBuffer, damages, timeStamp);
443 
444     std::shared_ptr<EFilter> contrastEFilter = EFilterFactory::Instance()->Create(CONTRAST_EFILTER);
445     Plugin::Any value = 50.f;
446     result = contrastEFilter->SetValue(KEY_FILTER_INTENSITY, value);
447     ASSERT_EQ(result, ErrorCode::SUCCESS);
448     imageEffect_->AddEFilter(contrastEFilter);
449 
450     result = imageEffect_->Start();
451     ASSERT_EQ(result, ErrorCode::SUCCESS);
452 
453     // contrast filter
454     imageEffect_->ConsumerBufferAvailable(surfaceBuffer, outBuffer, damages, timeStamp);
455     MockProducerSurface::ReleaseDmaBuffer(surfaceBuffer);
456 }
457 } // namespace Test
458 } // namespace Effect
459 } // namespace Media
460 } // namespace OHOS