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