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 "effect_memory_manager.h"
17 
18 #include "effect_log.h"
19 #include "effect_buffer.h"
20 #include "colorspace_helper.h"
21 
22 using namespace OHOS::ColorManager;
23 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
24 
25 namespace OHOS {
26 namespace Media {
27 namespace Effect {
Init(const std::shared_ptr<EffectBuffer> & srcEffectBuffer,const std::shared_ptr<EffectBuffer> & dstEffectBuffer)28 ErrorCode EffectMemoryManager::Init(const std::shared_ptr<EffectBuffer> &srcEffectBuffer,
29     const std::shared_ptr<EffectBuffer> &dstEffectBuffer)
30 {
31     AddFilterMemory(srcEffectBuffer, MemDataType::INPUT,
32         dstEffectBuffer == nullptr || srcEffectBuffer->buffer_ == dstEffectBuffer->buffer_);
33     AddFilterMemory(dstEffectBuffer, MemDataType::OUTPUT,
34         dstEffectBuffer != nullptr && srcEffectBuffer->buffer_ != dstEffectBuffer->buffer_);
35     return ErrorCode::SUCCESS;
36 }
37 
SetIPType(IPType ipType)38 void EffectMemoryManager::SetIPType(IPType ipType)
39 {
40     runningIPType_ = ipType;
41 }
42 
AddFilterMemory(const std::shared_ptr<EffectBuffer> & effectBuffer,MemDataType memDataType,bool isAllowModify)43 void EffectMemoryManager::AddFilterMemory(const std::shared_ptr<EffectBuffer> &effectBuffer, MemDataType memDataType,
44     bool isAllowModify)
45 {
46     // dst effect buffer is null while not set output data.
47     if (effectBuffer == nullptr || effectBuffer->buffer_ == nullptr) {
48         return;
49     }
50 
51     std::shared_ptr<Memory> memory = std::make_shared<Memory>();
52     memory->memoryData_ = std::make_shared<MemoryData>();
53     memory->memoryData_->data = effectBuffer->buffer_;
54     memory->memoryData_->memoryInfo.bufferInfo = *effectBuffer->bufferInfo_;
55     memory->memoryData_->memoryInfo.extra = effectBuffer->extraInfo_->surfaceBuffer;
56     memory->memoryData_->memoryInfo.bufferType = effectBuffer->extraInfo_->bufferType;
57     memory->memDataType_ = memDataType;
58     memory->isAllowModify_ = isAllowModify;
59     AddMemory(memory);
60 }
61 
UpdateColorSpaceIfNeed(std::shared_ptr<MemoryData> & memoryData)62 void UpdateColorSpaceIfNeed(std::shared_ptr<MemoryData> &memoryData)
63 {
64     const MemoryInfo &memoryInfo = memoryData->memoryInfo;
65     EffectColorSpace colorSpace = memoryInfo.bufferInfo.colorSpace_;
66     if (memoryInfo.bufferType != BufferType::DMA_BUFFER || memoryInfo.extra == nullptr ||
67         !ColorSpaceHelper::IsHdrColorSpace(colorSpace)) {
68         return;
69     }
70 
71     EFFECT_LOGI("UpdateColorSpaceIfNeed: UpdateColorSpace colorSpace=%{public}d", colorSpace);
72     auto *sb = static_cast<SurfaceBuffer *>(memoryInfo.extra);
73     ColorSpaceHelper::SetSurfaceBufferMetadataType(sb, CM_HDR_Metadata_Type::CM_IMAGE_HDR_VIVID_SINGLE);
74     ColorSpaceHelper::SetSurfaceBufferColorSpaceType(sb, CM_ColorSpaceType::CM_BT2020_HLG_FULL);
75 }
76 
AllocMemoryInner(MemoryInfo & allocMemInfo,BufferType allocBufferType)77 std::shared_ptr<Memory> AllocMemoryInner(MemoryInfo &allocMemInfo, BufferType allocBufferType)
78 {
79     EFFECT_LOGI("Alloc Memory! bufferType=%{public}d", allocBufferType);
80     std::unique_ptr<AbsMemory> absMemory = EffectMemory::CreateMemory(allocBufferType);
81     CHECK_AND_RETURN_RET_LOG(absMemory != nullptr, nullptr,
82         "absMemory is null! bufferType=%{public}d", allocBufferType);
83     std::shared_ptr<MemoryData> memoryData = absMemory->Alloc(allocMemInfo);
84     CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, nullptr,
85         "memoryData is null! bufferType=%{public}d", allocBufferType);
86 
87     UpdateColorSpaceIfNeed(memoryData);
88 
89     std::shared_ptr<Memory> memory = std::make_shared<Memory>();
90     memory->memoryData_ = memoryData;
91     memory->isAllowModify_ = true;
92 
93     return memory;
94 }
95 
AllocMemory(void * srcAddr,MemoryInfo & allocMemInfo)96 MemoryData *EffectMemoryManager::AllocMemory(void *srcAddr, MemoryInfo &allocMemInfo)
97 {
98     for (const auto &memory : memorys_) {
99         if (!memory->isAllowModify_ || memory->memoryData_->data == srcAddr) {
100             continue;
101         }
102 
103         const MemoryInfo &memInfo = memory->memoryData_->memoryInfo;
104         const BufferInfo &bufferInfo = memInfo.bufferInfo;
105         const BufferInfo &allocBufInfo = allocMemInfo.bufferInfo;
106         if (bufferInfo.width_ == allocBufInfo.width_ && bufferInfo.height_ == allocBufInfo.height_ &&
107             (allocMemInfo.bufferType == BufferType::DEFAULT || allocMemInfo.bufferType == memInfo.bufferType) &&
108             bufferInfo.formatType_ == allocBufInfo.formatType_ && bufferInfo.colorSpace_ == allocBufInfo.colorSpace_) {
109             EFFECT_LOGD("reuse memory. width=%{public}d, height=%{public}d, addr=%{public}p, format=%{public}d, "
110                 "bufferType=%{public}d, allocBufType=%{public}d", bufferInfo.width_, bufferInfo.height_,
111                 memory->memoryData_->data, bufferInfo.formatType_, memInfo.bufferType, allocMemInfo.bufferType);
112             return memory->memoryData_.get();
113         }
114     }
115 
116     BufferType allocBufferType = BufferType::DMA_BUFFER; // default alloc dma buffer
117     if (runningIPType_ == IPType::CPU) {
118         allocBufferType = BufferType::HEAP_MEMORY; // default alloc heap buffer on running with cpu filter
119     }
120     if (allocMemInfo.bufferType != BufferType::DEFAULT) {
121         allocBufferType = allocMemInfo.bufferType;
122     }
123     std::shared_ptr<Memory> memory = AllocMemoryInner(allocMemInfo, allocBufferType);
124     CHECK_AND_RETURN_RET_LOG(memory != nullptr, nullptr,
125         "AllocMemory fail! bufferType=%{public}d", allocBufferType);
126     AddMemory(memory);
127     EFFECT_LOGD("alloc new memory. memorys size=%{public}zu", memorys_.size());
128     return memory->memoryData_.get();
129 }
130 
AddMemory(std::shared_ptr<Memory> & memory)131 void EffectMemoryManager::AddMemory(std::shared_ptr<Memory> &memory)
132 {
133     CHECK_AND_RETURN_LOG(memory != nullptr, "memory is null!");
134     CHECK_AND_RETURN_LOG(memory->memoryData_ != nullptr && memory->memoryData_->data != nullptr,
135         "memory data is null!");
136     if (std::find(memorys_.begin(), memorys_.end(), memory) == memorys_.end()) {
137         memorys_.emplace_back(memory);
138     } else {
139         EFFECT_LOGW("memory is already add! memory=%{public}p", memory.get());
140     }
141 }
142 
GetAllocMemoryByAddr(void * addr)143 std::shared_ptr<Memory> EffectMemoryManager::GetAllocMemoryByAddr(void *addr)
144 {
145     for (auto &memory : memorys_) {
146         if (memory->memDataType_ != MemDataType::OTHER) {
147             continue;
148         }
149 
150         if (memory->memoryData_->data == addr) {
151             EFFECT_LOGD("addr is find! addr=%{public}p, bufferType=%{public}d",
152                 addr, memory->memoryData_->memoryInfo.bufferType);
153             return memory;
154         }
155     }
156     EFFECT_LOGI("addr is not find!");
157     return nullptr;
158 }
159 
GetMemoryByAddr(void * addr)160 std::shared_ptr<Memory> EffectMemoryManager::GetMemoryByAddr(void *addr)
161 {
162     auto it = std::find_if(memorys_.begin(), memorys_.end(), [&addr](const auto &item) {
163         return addr == item->memoryData_->data;
164     });
165 
166     return it == memorys_.end() ? nullptr : *it;
167 }
168 
RemoveMemory(std::shared_ptr<Memory> & memory)169 void EffectMemoryManager::RemoveMemory(std::shared_ptr<Memory> &memory)
170 {
171     auto it = std::find(memorys_.begin(), memorys_.end(), memory);
172     if (it != memorys_.end()) {
173         EFFECT_LOGD("EffectMemoryManager::RemoveMemory success!");
174         memorys_.erase(it);
175     }
176 }
177 
ClearMemory()178 void EffectMemoryManager::ClearMemory()
179 {
180     EFFECT_LOGD("EffectMemoryManager::ClearMemory");
181     memorys_.clear();
182 }
183 
Deinit()184 void EffectMemoryManager::Deinit()
185 {
186     for (auto it = memorys_.begin(); it != memorys_.end();) {
187         const MemDataType &memDataType_ = (*it)->memDataType_;
188         if (memDataType_ == MemDataType::INPUT || memDataType_ == MemDataType::OUTPUT) {
189             it = memorys_.erase(it);
190         } else {
191             ++it;
192         }
193     }
194     EFFECT_LOGD("EffectMemoryManager: Deinit memorySize=%{public}zu", memorys_.size());
195 }
196 } // namespace Effect
197 } // namespace Media
198 } // namespace OHOS