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