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