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 "efilter.h"
17 
18 #include "common_utils.h"
19 #include "effect_log.h"
20 #include "json_helper.h"
21 #include "efilter_factory.h"
22 #include "memcpy_helper.h"
23 #include "format_helper.h"
24 #include "colorspace_helper.h"
25 #include "render_thread.h"
26 #include "render_task.h"
27 #include "render_environment.h"
28 
29 namespace OHOS {
30 namespace Media {
31 namespace Effect {
32 const std::string EFilter::Parameter::KEY_DEFAULT_VALUE = "default_value";
33 
EFilter(const std::string & name)34 EFilter::EFilter(const std::string &name) : EFilterBase(name) {}
35 
36 EFilter::~EFilter() = default;
37 
SetValue(const std::string & key,Plugin::Any & value)38 ErrorCode EFilter::SetValue(const std::string &key, Plugin::Any &value)
39 {
40     auto it = values_.find(key);
41     if (it == values_.end()) {
42         values_.emplace(key, value);
43     } else {
44         values_[key] = value;
45     }
46     return ErrorCode::SUCCESS;
47 }
48 
GetValue(const std::string & key,Plugin::Any & value)49 ErrorCode EFilter::GetValue(const std::string &key, Plugin::Any &value)
50 {
51     if (key.empty()) {
52         return ErrorCode::ERR_INPUT_NULL;
53     }
54     auto it = values_.find(key);
55     if (it == values_.end()) {
56         EFFECT_LOGE("value is not set! key=%{public}s", key.c_str());
57         return ErrorCode::ERR_NO_VALUE;
58     }
59 
60     value = it->second;
61     return ErrorCode::SUCCESS;
62 }
63 
IsTextureInput()64 bool EFilter::IsTextureInput()
65 {
66     return false;
67 }
68 
Save(EffectJsonPtr & res)69 ErrorCode EFilter::Save(EffectJsonPtr &res)
70 {
71     res->Put("name", name_);
72     EffectJsonPtr jsonValues = JsonHelper::CreateObject();
73     for (auto value : values_) {
74         if (CommonUtils::ParseAnyAndAddToJson(value.first, value.second, jsonValues) !=
75             ErrorCode::SUCCESS) {
76             EFFECT_LOGE("not support switch to json! key:%{public}s", value.first.c_str());
77         }
78     }
79     if (jsonValues->IsValid()) {
80         res->Put("values", jsonValues);
81     }
82     return ErrorCode::SUCCESS;
83 }
84 
PreRender(IEffectFormat & format)85 ErrorCode EFilter::PreRender(IEffectFormat &format)
86 {
87     return ErrorCode::SUCCESS;
88 }
89 
GetPixelFormatCap(std::string & name)90 std::shared_ptr<PixelFormatCap> GetPixelFormatCap(std::string &name)
91 {
92     std::shared_ptr<PixelFormatCap> pixelFormatCap = std::make_shared<PixelFormatCap>();
93     std::shared_ptr<EffectInfo> effectInfo = EFilterFactory::Instance()->GetEffectInfo(name);
94     if (effectInfo == nullptr) {
95         EFFECT_LOGE("GetPixelFormatCap: GetEffectInfo fail! name=%{public}s", name.c_str());
96         return pixelFormatCap;
97     }
98 
99     pixelFormatCap->formats = effectInfo->formats_;
100     return pixelFormatCap;
101 }
102 
GetColorSpaceCap(std::string & name)103 std::shared_ptr<ColorSpaceCap> GetColorSpaceCap(std::string &name)
104 {
105     std::shared_ptr<ColorSpaceCap> colorSpaceCap = std::make_shared<ColorSpaceCap>();
106     std::shared_ptr<EffectInfo> effectInfo = EFilterFactory::Instance()->GetEffectInfo(name);
107     if (effectInfo == nullptr) {
108         EFFECT_LOGE("GetColorSpaceCap: GetEffectInfo fail! name=%{public}s", name.c_str());
109         return colorSpaceCap;
110     }
111 
112     colorSpaceCap->colorSpaces = effectInfo->colorSpaces_;
113     return colorSpaceCap;
114 }
115 
NegotiateColorSpace(std::vector<EffectColorSpace> & colorSpaces,std::unordered_set<EffectColorSpace> & filtersSupportedColorSpace)116 void NegotiateColorSpace(std::vector<EffectColorSpace> &colorSpaces,
117     std::unordered_set<EffectColorSpace> &filtersSupportedColorSpace)
118 {
119     for (auto it = filtersSupportedColorSpace.begin(); it != filtersSupportedColorSpace.end();) {
120         if (std::find(colorSpaces.begin(), colorSpaces.end(), *it) == colorSpaces.end()) {
121             it = filtersSupportedColorSpace.erase(it);
122         } else {
123             ++it;
124         }
125     }
126 }
127 
Negotiate(const std::string & inPort,const std::shared_ptr<Capability> & capability,std::shared_ptr<EffectContext> & context)128 void EFilter::Negotiate(const std::string &inPort, const std::shared_ptr<Capability> &capability,
129     std::shared_ptr<EffectContext> &context)
130 {
131     std::shared_ptr<Capability> outputCap = std::make_shared<Capability>(name_);
132     outputCap->pixelFormatCap_ = GetPixelFormatCap(name_);
133     outputCap->memNegotiatedCap_ = Negotiate(capability->memNegotiatedCap_, context);
134     outputCap->colorSpaceCap_ = GetColorSpaceCap(name_);
135     context->capNegotiate_->AddCapability(outputCap);
136     NegotiateColorSpace(outputCap->colorSpaceCap_->colorSpaces, context->filtersSupportedColorSpace_);
137     outputCap_ = outputCap;
138     outPorts_[0]->Negotiate(outputCap, context);
139 }
140 
AllocMemory(BufferType allocBufferType,EffectBuffer * buffer)141 std::shared_ptr<MemoryData> AllocMemory(BufferType allocBufferType, EffectBuffer *buffer)
142 {
143     std::unique_ptr<AbsMemory> absMemory = EffectMemory::CreateMemory(allocBufferType);
144     CHECK_AND_RETURN_RET_LOG(absMemory != nullptr, nullptr,
145         "memory create fail! allocatorType=%{public}d", allocBufferType);
146 
147     CHECK_AND_RETURN_RET_LOG(buffer != nullptr && buffer->extraInfo_ != nullptr, nullptr,
148         "alloc memory fail, buffer or buffer extraInfo is null!");
149     MemoryInfo allocMemInfo = {
150         .bufferInfo = *buffer->bufferInfo_,
151         .extra = static_cast<void *>(buffer->extraInfo_->surfaceBuffer),
152     };
153     std::shared_ptr<MemoryData> memoryData = absMemory->Alloc(allocMemInfo);
154     CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, nullptr,
155         "memoryData is null! bufferType=%{public}d", allocBufferType);
156     return memoryData;
157 }
158 
CreateEffectBuffer(EffectBuffer * buffer,std::shared_ptr<MemoryData> & allocMemData,std::shared_ptr<EffectBuffer> & effectBuffer)159 ErrorCode CreateEffectBuffer(EffectBuffer *buffer, std::shared_ptr<MemoryData> &allocMemData,
160     std::shared_ptr<EffectBuffer> &effectBuffer)
161 {
162     CHECK_AND_RETURN_RET_LOG(allocMemData != nullptr, ErrorCode::ERR_ALLOC_MEMORY_FAIL, "alloc memory fail!");
163     MemoryInfo &allocMemInfo = allocMemData->memoryInfo;
164     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
165     *bufferInfo = allocMemInfo.bufferInfo;
166     std::shared_ptr<ExtraInfo> extraInfo = std::make_shared<ExtraInfo>();
167     *extraInfo = *buffer->extraInfo_;
168     extraInfo->surfaceBuffer = (allocMemInfo.bufferType == BufferType::DMA_BUFFER) ?
169         static_cast<SurfaceBuffer *>(allocMemInfo.extra) : nullptr;
170     effectBuffer = std::make_shared<EffectBuffer>(bufferInfo, allocMemData->data, extraInfo);
171     return ErrorCode::SUCCESS;
172 }
173 
IpTypeConvert(const std::shared_ptr<EffectBuffer> & buffer,std::shared_ptr<EffectContext> & context)174 std::shared_ptr<EffectBuffer> EFilter::IpTypeConvert(const std::shared_ptr<EffectBuffer> &buffer,
175     std::shared_ptr<EffectContext> &context)
176 {
177     IPType runningIPType = context->ipType_;
178     IEffectFormat formatType = buffer->bufferInfo_->formatType_;
179     std::shared_ptr<PixelFormatCap> pixelFormatCap = GetPixelFormatCap(name_);
180     std::map<IEffectFormat, std::vector<IPType>> &formats = pixelFormatCap->formats;
181     auto it = formats.find(formatType);
182     if (it == formats.end() && runningIPType == IPType::CPU) {
183         it = formats.find(IEffectFormat::RGBA8888);
184     }
185     CHECK_AND_RETURN_RET_LOG(it != formats.end(), buffer,
186         "format not support! format=%{public}d, name=%{public}s", formatType, name_.c_str());
187     std::shared_ptr<EffectBuffer> source = buffer;
188     CHECK_AND_RETURN_RET_LOG(runningIPType != IPType::DEFAULT, buffer, "runningIPType is default");
189 
190     if (std::find(it->second.begin(), it->second.end(), runningIPType) == it->second.end()) {
191         if (runningIPType == IPType::GPU) {
192             source = ConvertFromGPU2CPU(buffer, context, source);
193         } else {
194             source = ConvertFromCPU2GPU(buffer, context, source);
195         }
196     }
197     return source;
198 }
199 
ConvertFromGPU2CPU(const std::shared_ptr<EffectBuffer> & buffer,std::shared_ptr<EffectContext> & context,std::shared_ptr<EffectBuffer> & source)200 std::shared_ptr<EffectBuffer> EFilter::ConvertFromGPU2CPU(const std::shared_ptr<EffectBuffer> &buffer,
201     std::shared_ptr<EffectContext> &context, std::shared_ptr<EffectBuffer> &source)
202 {
203     CHECK_AND_RETURN_RET_LOG(buffer != nullptr, buffer, "ConvertFromGPU2CPU fail, buffer is null!");
204     EFFECT_LOGE("ConvertFromGPU2CPU");
205     context->ipType_ = IPType::CPU;
206     MemoryInfo memInfo = {
207         .bufferInfo = {
208             .width_ = buffer->tex->Width(),
209             .height_ = buffer->tex->Height(),
210             .len_ = FormatHelper::CalculateSize(buffer->tex->Width(), buffer->tex->Height(), IEffectFormat::RGBA8888),
211             .formatType_ = IEffectFormat::RGBA8888,
212         },
213         .bufferType = BufferType::DMA_BUFFER,
214     };
215     MemoryData *memoryData = context->memoryManager_->AllocMemory(nullptr, memInfo);
216     CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, buffer, "Alloc new memory fail!");
217     MemoryInfo &allocMemInfo = memoryData->memoryInfo;
218     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
219     *bufferInfo = allocMemInfo.bufferInfo;
220     std::shared_ptr<ExtraInfo> extraInfo = std::make_shared<ExtraInfo>();
221     *extraInfo = *buffer->extraInfo_;
222     extraInfo->bufferType = allocMemInfo.bufferType;
223     extraInfo->surfaceBuffer = static_cast<SurfaceBuffer *>(allocMemInfo.extra);
224     std::shared_ptr<EffectBuffer> input = std::make_shared<EffectBuffer>(bufferInfo, memoryData->data,
225         extraInfo);
226     if (context->renderEnvironment_->GetOutputType() == DataType::NATIVE_WINDOW) {
227         context->renderEnvironment_->DrawFlipSurfaceBufferFromTex(buffer->tex, extraInfo->surfaceBuffer,
228             bufferInfo->formatType_);
229         extraInfo->surfaceBuffer->InvalidateCache();
230     } else {
231         context->renderEnvironment_->ConvertTextureToBuffer(buffer->tex, input.get());
232     }
233     input->extraInfo_->dataType = DataType::SURFACE_BUFFER;
234     input->extraInfo_->bufferType = BufferType::DMA_BUFFER;
235     source = input;
236     return source;
237 }
238 
ConvertFromCPU2GPU(const std::shared_ptr<EffectBuffer> & buffer,std::shared_ptr<EffectContext> & context,std::shared_ptr<EffectBuffer> & source)239 std::shared_ptr<EffectBuffer> EFilter::ConvertFromCPU2GPU(const std::shared_ptr<EffectBuffer> &buffer,
240     std::shared_ptr<EffectContext> &context, std::shared_ptr<EffectBuffer> &source)
241 {
242     if (context->renderEnvironment_->GetEGLStatus() != EGLStatus::READY) {
243         context->renderEnvironment_->Init();
244         context->renderEnvironment_->Prepare();
245     }
246     context->ipType_ = IPType::GPU;
247     if (source->extraInfo_->surfaceBuffer != nullptr) {
248         source->extraInfo_->surfaceBuffer->FlushCache();
249     }
250     source = context->renderEnvironment_->ConvertBufferToTexture(buffer.get());
251     if (context->renderEnvironment_->GetOutputType() == DataType::NATIVE_WINDOW) {
252         RenderTexturePtr tempTex = context->renderEnvironment_->RequestBuffer(source->tex->Width(),
253             source->tex->Height());
254         context->renderEnvironment_->DrawFlipTex(source->tex, tempTex);
255         source->tex = tempTex;
256     }
257     return source;
258 }
259 
PushData(const std::string & inPort,const std::shared_ptr<EffectBuffer> & buffer,std::shared_ptr<EffectContext> & context)260 ErrorCode EFilter::PushData(const std::string &inPort, const std::shared_ptr<EffectBuffer> &buffer,
261     std::shared_ptr<EffectContext> &context)
262 {
263     IPType preIPType = context->ipType_;
264     std::shared_ptr<EffectBuffer> source = IpTypeConvert(buffer, context);
265     IPType runningIPType = context->ipType_;
266 
267     if (runningIPType == IPType::GPU) {
268         ErrorCode res = Render(source.get(), context);
269         return res;
270     }
271 
272     std::shared_ptr<MemNegotiatedCap> &memNegotiatedCap = outputCap_->memNegotiatedCap_;
273     EffectBuffer *output = preIPType != runningIPType ? source.get()
274         : context->renderStrategy_->ChooseBestOutput(source.get(), memNegotiatedCap);
275     if (source.get() == output) {
276         ErrorCode res = Render(source.get(), context);
277         CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
278             "Render input fail! filterName=%{public}s", name_.c_str());
279         return ErrorCode::SUCCESS;
280     }
281 
282     std::shared_ptr<EffectBuffer> effectBuffer = nullptr;
283     if (output == nullptr || source.get() == output) {
284         MemoryInfo memInfo = {
285             .bufferInfo = {
286                 .width_ = memNegotiatedCap->width,
287                 .height_ = memNegotiatedCap->height,
288                 .len_ = FormatHelper::CalculateSize(
289                     memNegotiatedCap->width, memNegotiatedCap->height, buffer->bufferInfo_->formatType_),
290                 .formatType_ = buffer->bufferInfo_->formatType_,
291                 .colorSpace_ = buffer->bufferInfo_->colorSpace_,
292             }
293         };
294         MemoryData *memoryData = context->memoryManager_->AllocMemory(source->buffer_, memInfo);
295         CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, ErrorCode::ERR_ALLOC_MEMORY_FAIL, "Alloc new memory fail!");
296         MemoryInfo &allocMemInfo = memoryData->memoryInfo;
297         std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
298         *bufferInfo = allocMemInfo.bufferInfo;
299         std::shared_ptr<ExtraInfo> extraInfo = std::make_shared<ExtraInfo>();
300         *extraInfo = *source->extraInfo_;
301         extraInfo->bufferType = allocMemInfo.bufferType;
302         extraInfo->surfaceBuffer = (allocMemInfo.bufferType == BufferType::DMA_BUFFER) ?
303             static_cast<SurfaceBuffer *>(allocMemInfo.extra) : nullptr;
304         effectBuffer = std::make_shared<EffectBuffer>(bufferInfo, memoryData->data, extraInfo);
305     }
306     if (effectBuffer != nullptr) {
307         output = effectBuffer.get();
308     }
309     ErrorCode res = Render(source.get(), output, context);
310     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "Render inout fail! filterName=%{public}s", name_.c_str());
311     return PushData(output, context);
312 }
313 
OnPushDataPortsEmpty(std::shared_ptr<EffectBuffer> & buffer,std::shared_ptr<EffectContext> & context,std::string & name)314 ErrorCode OnPushDataPortsEmpty(std::shared_ptr<EffectBuffer> &buffer, std::shared_ptr<EffectContext> &context,
315     std::string &name)
316 {
317     EffectBuffer *input = context->renderStrategy_->GetInput();
318     if (input == nullptr) {
319         EFFECT_LOGE("input effect buffer is null! filterName=%{public}s", name.c_str());
320         return ErrorCode::ERR_SRC_EFFECT_BUFFER_NULL;
321     }
322 
323     // efilter modify input buffer directly
324     if (input->buffer_ == buffer->buffer_) {
325         return ColorSpaceHelper::UpdateMetadata(buffer.get());
326     }
327 
328     // efilter create new buffer and inout with the same buffer.
329     EffectBuffer *output = context->renderStrategy_->GetOutput();
330     if (output == nullptr || input->buffer_ == output->buffer_) {
331         return CommonUtils::ModifyPixelMapProperty(buffer->extraInfo_->pixelMap, buffer, context->memoryManager_);
332     }
333     EFFECT_LOGW("not support different input and output buffer! filterName=%{public}s", name.c_str());
334     return ErrorCode::ERR_UNSUPPORTED_INOUT_WITH_DIFF_BUFFER;
335 }
336 
PushData(EffectBuffer * buffer,std::shared_ptr<EffectContext> & context)337 ErrorCode EFilter::PushData(EffectBuffer *buffer, std::shared_ptr<EffectContext> &context)
338 {
339     CHECK_AND_RETURN_RET_LOG(buffer != nullptr, ErrorCode::ERR_INPUT_NULL,
340         "PushData: input effect buffer is null! filterName=%{public}s", name_.c_str());
341 
342     std::shared_ptr<EffectBuffer> effectBuffer =
343         std::make_shared<EffectBuffer>(buffer->bufferInfo_, buffer->buffer_, buffer->extraInfo_);
344     effectBuffer->tex = buffer->tex;
345     if (outPorts_.empty()) {
346         return OnPushDataPortsEmpty(effectBuffer, context, name_);
347     }
348 
349     return outPorts_[0]->PushData(effectBuffer, context);
350 }
351 
Negotiate(const std::shared_ptr<MemNegotiatedCap> & input,std::shared_ptr<EffectContext> & context)352 std::shared_ptr<MemNegotiatedCap> EFilter::Negotiate(const std::shared_ptr<MemNegotiatedCap> &input,
353     std::shared_ptr<EffectContext> &context)
354 {
355     std::shared_ptr<MemNegotiatedCap> output = input;
356     return output;
357 }
358 
CalculateEFilterIPType(IEffectFormat & formatType,IPType & ipType)359 ErrorCode EFilter::CalculateEFilterIPType(IEffectFormat &formatType, IPType &ipType)
360 {
361     std::shared_ptr<PixelFormatCap> pixelFormatCap = GetPixelFormatCap(name_);
362     std::map<IEffectFormat, std::vector<IPType>> &formats = pixelFormatCap->formats;
363     auto it = formats.find(formatType);
364     CHECK_AND_RETURN_RET_LOG(it != formats.end(), ErrorCode::ERR_UNSUPPORTED_FORMAT_TYPE,
365         "format not support! format=%{public}d, name=%{public}s", formatType, name_.c_str());
366 
367     if (std::find(it->second.begin(), it->second.end(), IPType::GPU) == it->second.end()) {
368         ipType = IPType::CPU;
369     } else {
370         ipType = IPType::GPU;
371     }
372     return ErrorCode::SUCCESS;
373 }
374 
CreateDmaEffectBufferIfNeed(IPType runningType,EffectBuffer * current,EffectBuffer * src,std::shared_ptr<EffectContext> & context,std::shared_ptr<EffectBuffer> & effectBuffer)375 ErrorCode CreateDmaEffectBufferIfNeed(IPType runningType, EffectBuffer *current, EffectBuffer *src,
376     std::shared_ptr<EffectContext> &context, std::shared_ptr<EffectBuffer> &effectBuffer)
377 {
378     if (runningType == IPType::CPU) {
379         return ErrorCode::SUCCESS;
380     }
381     if (runningType == IPType::GPU && current->extraInfo_->bufferType == BufferType::DMA_BUFFER) {
382         if (current == src || current->buffer_ != src->buffer_) {
383             return ErrorCode::SUCCESS;
384         }
385     }
386 
387     MemoryInfo memInfo = {
388         .bufferInfo = *current->bufferInfo_,
389         .bufferType = BufferType::DMA_BUFFER,
390     };
391     memInfo.bufferInfo.colorSpace_ = src->bufferInfo_->colorSpace_;
392     MemoryData *memData = context->memoryManager_->AllocMemory(src->buffer_, memInfo);
393     CHECK_AND_RETURN_RET_LOG(memData != nullptr, ErrorCode::ERR_ALLOC_MEMORY_FAIL, "Alloc memory fail!");
394 
395     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
396     *bufferInfo = memData->memoryInfo.bufferInfo;
397     std::shared_ptr<ExtraInfo> extraInfo = std::make_shared<ExtraInfo>();
398     *extraInfo = *src->extraInfo_;
399     extraInfo->bufferType = memData->memoryInfo.bufferType;
400     extraInfo->surfaceBuffer = (memData->memoryInfo.bufferType == BufferType::DMA_BUFFER) ?
401         static_cast<SurfaceBuffer *>(memData->memoryInfo.extra) : nullptr;
402     effectBuffer = std::make_shared<EffectBuffer>(bufferInfo, memData->data, extraInfo);
403     return ErrorCode::SUCCESS;
404 }
405 
RenderWithGPU(std::shared_ptr<EffectContext> & context,std::shared_ptr<EffectBuffer> & src,std::shared_ptr<EffectBuffer> & dst,bool needModifySource)406 ErrorCode EFilter::RenderWithGPU(std::shared_ptr<EffectContext> &context, std::shared_ptr<EffectBuffer> &src,
407     std::shared_ptr<EffectBuffer> &dst, bool needModifySource)
408 {
409     if (context->renderEnvironment_->GetEGLStatus() != EGLStatus::READY) {
410         context->renderEnvironment_->Init();
411         context->renderEnvironment_->Prepare();
412     }
413     std::shared_ptr<EffectBuffer> buffer = nullptr;
414     context->renderEnvironment_->BeginFrame();
415     if (src->bufferInfo_->formatType_ == IEffectFormat::RGBA8888) {
416         context->renderEnvironment_->GenMainTex(src, buffer);
417     } else {
418         context->renderEnvironment_->ConvertYUV2RGBA(src, buffer);
419     }
420 
421     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
422     bufferInfo = dst->bufferInfo_;
423     std::shared_ptr<ExtraInfo> extraInfo = std::make_shared<ExtraInfo>();
424     extraInfo->dataType = DataType::TEX;
425     std::shared_ptr<EffectBuffer> effectBuffer = std::make_shared<EffectBuffer>(bufferInfo, nullptr, extraInfo);
426     effectBuffer->tex = context->renderEnvironment_->RequestBuffer(bufferInfo->width_, bufferInfo->height_);
427     ErrorCode res = Render(buffer.get(), effectBuffer.get(), context);
428     if (needModifySource) {
429         CommonUtils::ModifyPixelMapPropertyForTexture(dst->extraInfo_->pixelMap, effectBuffer, context);
430     } else {
431         context->renderEnvironment_->ConvertTextureToBuffer(effectBuffer->tex, dst.get());
432     }
433     return res;
434 }
435 
GetSupportedColorSpace(std::string & name,std::unordered_set<EffectColorSpace> & filtersSupportedColorSpace)436 void GetSupportedColorSpace(std::string &name, std::unordered_set<EffectColorSpace> &filtersSupportedColorSpace)
437 {
438     std::unordered_set<EffectColorSpace> allSupportedColorSpaces = ColorSpaceManager::GetAllSupportedColorSpaces();
439     std::for_each(allSupportedColorSpaces.begin(), allSupportedColorSpaces.end(), [&](const auto &item) {
440         filtersSupportedColorSpace.emplace(item);
441     });
442 
443     std::shared_ptr<ColorSpaceCap> colorSpaceCap = GetColorSpaceCap(name);
444     NegotiateColorSpace(colorSpaceCap->colorSpaces, filtersSupportedColorSpace);
445 }
446 
CreateEffectContext(std::shared_ptr<EffectBuffer> & src,std::shared_ptr<EffectBuffer> & dst,std::string & name)447 std::shared_ptr<EffectContext> CreateEffectContext(std::shared_ptr<EffectBuffer> &src,
448     std::shared_ptr<EffectBuffer> &dst, std::string &name)
449 {
450     std::shared_ptr<EffectContext> context = std::make_shared<EffectContext>();
451     context->memoryManager_ = std::make_shared<EffectMemoryManager>();
452     context->renderStrategy_ = std::make_shared<RenderStrategy>();
453     context->colorSpaceManager_ = std::make_shared<ColorSpaceManager>();
454     GetSupportedColorSpace(name, context->filtersSupportedColorSpace_);
455 
456     context->memoryManager_->Init(src, dst); // local variable and not need invoke ClearMemory
457     context->renderStrategy_->Init(src, dst);
458     context->colorSpaceManager_->Init(src, dst);
459 
460     return context;
461 }
462 
CheckAndUpdateEffectBufferIfNeed(std::shared_ptr<EffectBuffer> & src,std::shared_ptr<EffectContext> & context,std::string & name,std::shared_ptr<EffectBuffer> & dst)463 ErrorCode CheckAndUpdateEffectBufferIfNeed(std::shared_ptr<EffectBuffer> &src, std::shared_ptr<EffectContext> &context,
464     std::string &name, std::shared_ptr<EffectBuffer> &dst)
465 {
466     if (src->buffer_ == dst->buffer_) {
467         dst = src;
468     }
469 
470     ErrorCode res = ColorSpaceHelper::ConvertColorSpace(src, context);
471     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
472         "CheckAndUpdateEffectBufferIfNeed: ConvertColorSpace fail! res=%{public}d, name=%{public}s", res, name.c_str());
473 
474     if (src->buffer_ != dst->buffer_) {
475         // color space is same or not after covert color space if needed.
476         EffectColorSpace srcColorSpace = src->bufferInfo_->colorSpace_;
477         EffectColorSpace dstColorSpace = dst->bufferInfo_->colorSpace_;
478         bool isSrcHdr = ColorSpaceHelper::IsHdrColorSpace(srcColorSpace);
479         bool isDstHdr = ColorSpaceHelper::IsHdrColorSpace(dstColorSpace);
480         CHECK_AND_RETURN_RET_LOG(isSrcHdr == isDstHdr, ErrorCode::ERR_FILTER_NOT_SUPPORT_INPUT_OUTPUT_COLORSPACE,
481             "CheckAndUpdateEffectBufferIfNeed: input and output color space not support! srcRealColorSpace=%{public}d, "
482             "dstColorSpace=%{public}d", srcColorSpace, dstColorSpace);
483     }
484 
485     return ErrorCode::SUCCESS;
486 }
487 
UseTextureInput()488 ErrorCode EFilter::UseTextureInput()
489 {
490     std::shared_ptr<EffectContext> tempContext = std::make_shared<EffectContext>();
491     tempContext->ipType_ = IPType::GPU;
492     ErrorCode result = Render(nullptr, nullptr, tempContext);
493     CHECK_AND_RETURN_RET_LOG(result == ErrorCode::SUCCESS, result, "Render: render with input and output fail!");
494     return ErrorCode::SUCCESS;
495 }
496 
RenderInner(std::shared_ptr<EffectBuffer> & src,std::shared_ptr<EffectBuffer> & dst)497 ErrorCode EFilter::RenderInner(std::shared_ptr<EffectBuffer> &src, std::shared_ptr<EffectBuffer> &dst)
498 {
499     if (IsTextureInput()) {
500         return UseTextureInput();
501     }
502     EffectBuffer *srcBuf = src.get();
503     EffectBuffer *dstBuf = dst.get();
504     CHECK_AND_RETURN_RET_LOG(srcBuf != nullptr && dstBuf != nullptr, ErrorCode::ERR_INPUT_NULL, "src or dst is null!");
505 
506     outPorts_.clear();
507     void *originBuffer = src->buffer_;
508 
509     std::shared_ptr<EffectContext> context = CreateEffectContext(src, dst, name_);
510     ErrorCode res = CheckAndUpdateEffectBufferIfNeed(src, context, name_, dst);
511     CHECK_AND_RETURN_RET(res == ErrorCode::SUCCESS, res);
512     bool needMotifySource = (src->buffer_ != originBuffer) && (src->buffer_ == dst->buffer_);
513 
514     IPType runningType = IPType::DEFAULT;
515     res = CalculateEFilterIPType(src->bufferInfo_->formatType_, runningType);
516     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
517         "Render CalculateEFilterIPType fail! name=%{public}s", name_.c_str());
518     InitContext(context, runningType);
519     std::shared_ptr<EffectBuffer> input = nullptr;
520     res = CreateDmaEffectBufferIfNeed(runningType, srcBuf, srcBuf, context, input);
521     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
522         "Render CreateDmaEffectBuffer src fail! res=%{public}d, name=%{public}s", res, name_.c_str());
523     if (input != nullptr) {
524         MemcpyHelper::CopyData(srcBuf, input.get());
525     }
526 
527     if (runningType == IPType::GPU) {
528         return RenderWithGPU(context, src, dst, needMotifySource);
529     }
530 
531     if (src->buffer_ != dst->buffer_) {
532         std::shared_ptr<EffectBuffer> output = nullptr;
533         res =
534             CreateDmaEffectBufferIfNeed(runningType, dstBuf, input == nullptr ? srcBuf : input.get(), context, output);
535         CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
536             "Render CreateDmaEffectBuffer dst fail! res=%{public}d, name=%{public}s", res, name_.c_str());
537         res = Render(input == nullptr ? srcBuf : input.get(), output == nullptr ? dstBuf : output.get(), context);
538         CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "Render: render with input and output fail!");
539         res = ColorSpaceHelper::UpdateMetadata(output == nullptr ? dst.get() : output.get());
540         CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "OnPushDataPortsEmpty: UpdateMetadata fail!");
541         if (output != nullptr) {
542             MemcpyHelper::CopyData(output.get(), dstBuf);
543         }
544     } else {
545         res = Render(srcBuf, context);
546         CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "Render: render with input fail!");
547     }
548     return ErrorCode::SUCCESS;
549 }
550 
InitContext(std::shared_ptr<EffectContext> & context,IPType & runningType)551 void EFilter::InitContext(std::shared_ptr<EffectContext> &context, IPType &runningType)
552 {
553     context->ipType_ = runningType;
554     context->memoryManager_->SetIPType(runningType);
555 
556     context->renderEnvironment_ = std::make_shared<RenderEnvironment>();
557     context->renderEnvironment_->Init();
558     context->renderEnvironment_->Prepare();
559 }
560 
Render(std::shared_ptr<EffectBuffer> & src,std::shared_ptr<EffectBuffer> & dst)561 ErrorCode EFilter::Render(std::shared_ptr<EffectBuffer> &src, std::shared_ptr<EffectBuffer> &dst)
562 {
563     ErrorCode res = RenderInner(src, dst);
564     if (res != ErrorCode::SUCCESS) {
565         return res;
566     }
567 
568     // update exif info
569     if (!IsTextureInput()) {
570         CommonUtils::UpdateImageExifDateTime(dst->extraInfo_->pixelMap);
571     }
572     return ErrorCode::SUCCESS;
573 }
574 } // namespace Effect
575 } // namespace Media
576 } // namespace OHOS