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