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