1 /*
2 * Copyright (C) 2021 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 "memory_manager.h"
17
18 #include <cerrno>
19 #include <unistd.h>
20 #include "image_log.h"
21 #include "image_utils.h"
22 #include "media_errors.h"
23 #include "securec.h"
24
25 #if !defined(_WIN32) && !defined(_APPLE) &&!defined(IOS_PLATFORM) &&!defined(ANDROID_PLATFORM)
26 #include <sys/mman.h>
27 #include "ashmem.h"
28 #include "surface_buffer.h"
29 #define SUPPORT_SHARED_MEMORY
30 #endif
31
32 #undef LOG_DOMAIN
33 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
34
35 #undef LOG_TAG
36 #define LOG_TAG "MemoryManager"
37
38 namespace OHOS {
39 namespace Media {
40 static const size_t SIZE_ZERO = 0;
41 static const int LINUX_SUCCESS = 0;
42 // Define pixel map malloc max size 600MB
43 constexpr int32_t PIXEL_MAP_MAX_RAM_SIZE = 600 * 1024 * 1024;
44
Create()45 uint32_t HeapMemory::Create()
46 {
47 IMAGE_LOGD("HeapMemory::Create IN");
48 if (data.data != nullptr) {
49 IMAGE_LOGD("HeapMemory::Create has created");
50 return SUCCESS;
51 }
52 if (data.size == 0 || data.size > PIXEL_MAP_MAX_RAM_SIZE) {
53 IMAGE_LOGE("HeapMemory::Create Invalid value of bufferSize");
54 return ERR_IMAGE_DATA_ABNORMAL;
55 }
56 data.data = static_cast<uint8_t *>(malloc(data.size));
57 if (data.data == nullptr) {
58 IMAGE_LOGE("HeapMemory::Create malloc buffer failed");
59 return ERR_IMAGE_MALLOC_ABNORMAL;
60 }
61 #if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
62 memset_s(data.data, data.size, 0, data.size);
63 #endif
64 return SUCCESS;
65 }
66
Release()67 uint32_t HeapMemory::Release()
68 {
69 #if !defined(IOS_PLATFORM) &&!defined(ANDROID_PLATFORM)
70 IMAGE_LOGD("HeapMemory::Release IN");
71 if (data.data == nullptr) {
72 IMAGE_LOGI("HeapMemory::Release nullptr data");
73 return ERR_IMAGE_DATA_ABNORMAL;
74 }
75 free(data.data);
76 data.data = nullptr;
77 #endif
78 return SUCCESS;
79 }
80
ReleaseSharedMemory(int * fdPtr,uint8_t * ptr=nullptr,size_t size=SIZE_ZERO)81 static inline void ReleaseSharedMemory(int* fdPtr, uint8_t* ptr = nullptr, size_t size = SIZE_ZERO)
82 {
83 #if !defined(IOS_PLATFORM) &&!defined(ANDROID_PLATFORM)
84 if (ptr != nullptr && ptr != MAP_FAILED) {
85 ::munmap(ptr, size);
86 }
87 if (fdPtr != nullptr) {
88 ::close(*fdPtr);
89 }
90 #endif
91 }
92
Create()93 uint32_t SharedMemory::Create()
94 {
95 #ifdef SUPPORT_SHARED_MEMORY
96 IMAGE_LOGD("SharedMemory::Create IN tag %{public}s, data size %{public}zu",
97 data.tag == nullptr ? "nullptr" : data.tag, data.size);
98
99 if (data.tag == nullptr || data.size == SIZE_ZERO) {
100 IMAGE_LOGE("SharedMemory::Create tag is nullptr or data size %{public}zu", data.size);
101 return ERR_IMAGE_DATA_ABNORMAL;
102 }
103 auto fdPtr = std::make_unique<int>();
104 *fdPtr = AshmemCreate(data.tag, data.size);
105 if (*fdPtr < 0) {
106 IMAGE_LOGE("SharedMemory::Create AshmemCreate fd:[%{public}d].", *fdPtr);
107 return ERR_IMAGE_DATA_ABNORMAL;
108 }
109 if (AshmemSetProt(*fdPtr, PROT_READ | PROT_WRITE) < LINUX_SUCCESS) {
110 IMAGE_LOGE("SharedMemory::Create AshmemSetProt errno %{public}d.", errno);
111 ReleaseSharedMemory(fdPtr.get());
112 return ERR_IMAGE_DATA_ABNORMAL;
113 }
114 data.data = ::mmap(nullptr, data.size, PROT_READ | PROT_WRITE, MAP_SHARED, *fdPtr, 0);
115 if (data.data == MAP_FAILED) {
116 IMAGE_LOGE("SharedMemory::Create mmap failed, errno:%{public}d", errno);
117 ReleaseSharedMemory(fdPtr.get(), static_cast<uint8_t*>(data.data), data.size);
118 return ERR_IMAGE_DATA_ABNORMAL;
119 }
120 extend.size = sizeof(int);
121 extend.data = fdPtr.release();
122 return SUCCESS;
123 #else
124 IMAGE_LOGE("SharedMemory::Create unsupported");
125 return ERR_IMAGE_DATA_UNSUPPORT;
126 #endif
127 }
128
Release()129 uint32_t SharedMemory::Release()
130 {
131 #ifdef SUPPORT_SHARED_MEMORY
132 IMAGE_LOGD("SharedMemory::Release IN");
133 ReleaseSharedMemory(static_cast<int*>(extend.data), static_cast<uint8_t*>(data.data), data.size);
134 data.data = nullptr;
135 data.size = SIZE_ZERO;
136 if (extend.data != nullptr) {
137 free(extend.data);
138 extend.data = nullptr;
139 extend.size = SIZE_ZERO;
140 }
141 return SUCCESS;
142 #else
143 IMAGE_LOGE("SharedMemory::Release unsupported");
144 return ERR_IMAGE_DATA_UNSUPPORT;
145 #endif
146 }
147
148 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
GetRequestBufferFormatWithPixelFormat(const PixelFormat format)149 GraphicPixelFormat GetRequestBufferFormatWithPixelFormat(const PixelFormat format)
150 {
151 switch (format) {
152 case PixelFormat::RGBA_1010102:
153 return GRAPHIC_PIXEL_FMT_RGBA_1010102;
154 case PixelFormat::ASTC_4x4:
155 case PixelFormat::ASTC_6x6:
156 case PixelFormat::ASTC_8x8:
157 return GRAPHIC_PIXEL_FMT_BLOB;
158 case PixelFormat::NV12:
159 return GRAPHIC_PIXEL_FMT_YCBCR_420_SP;
160 case PixelFormat::NV21:
161 return GRAPHIC_PIXEL_FMT_YCRCB_420_SP;
162 case PixelFormat::BGRA_8888:
163 return GRAPHIC_PIXEL_FMT_BGRA_8888;
164 case PixelFormat::YCRCB_P010:
165 return GRAPHIC_PIXEL_FMT_YCRCB_P010;
166 case PixelFormat::YCBCR_P010:
167 return GRAPHIC_PIXEL_FMT_YCBCR_P010;
168 case PixelFormat::RGBA_F16:
169 return GRAPHIC_PIXEL_FMT_RGBA16_FLOAT;
170 default:
171 return GRAPHIC_PIXEL_FMT_RGBA_8888;
172 }
173 }
174 #endif
175
Create()176 uint32_t DmaMemory::Create()
177 {
178 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
179 IMAGE_LOGE("Unsupport dma mem alloc");
180 return ERR_IMAGE_DATA_UNSUPPORT;
181 #else
182 sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
183 GraphicPixelFormat format = GetRequestBufferFormatWithPixelFormat(data.format);
184 BufferRequestConfig requestConfig = {
185 .width = data.desiredSize.width,
186 .height = data.desiredSize.height,
187 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
188 .format = format, // PixelFormat
189 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
190 .timeout = 0,
191 };
192 GSError ret = sb->Alloc(requestConfig);
193 if (ret != GSERROR_OK) {
194 IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
195 return ERR_DMA_NOT_EXIST;
196 }
197 void* nativeBuffer = sb.GetRefPtr();
198 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
199 if (err != OHOS::GSERROR_OK) {
200 IMAGE_LOGE("NativeBufferReference failed");
201 return ERR_DMA_DATA_ABNORMAL;
202 }
203 data.data = static_cast<uint8_t*>(sb->GetVirAddr());
204 extend.size = data.size;
205 extend.data = nativeBuffer;
206 return SUCCESS;
207 #endif
208 }
209
Release()210 uint32_t DmaMemory::Release()
211 {
212 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
213 IMAGE_LOGE("Unsupport dma mem release");
214 return ERR_IMAGE_DATA_UNSUPPORT;
215 #else
216 data.data = nullptr;
217 data.size = SIZE_ZERO;
218 if (extend.data != nullptr) {
219 int32_t err = ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(extend.data));
220 if (err != OHOS::GSERROR_OK) {
221 IMAGE_LOGE("NativeBufferReference failed");
222 return ERR_DMA_DATA_ABNORMAL;
223 }
224 extend.data = nullptr;
225 extend.size = SIZE_ZERO;
226 }
227 return SUCCESS;
228 #endif
229 }
230
CreateMemory(AllocatorType type,MemoryData & data)231 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data)
232 {
233 MemoryData extend{};
234 return CreateMemory(type, data, extend);
235 }
236
CreateMemory(AllocatorType type,MemoryData & data,MemoryData & extend)237 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data, MemoryData &extend)
238 {
239 std::unique_ptr<AbsMemory> res = nullptr;
240 switch (type) {
241 case AllocatorType::SHARE_MEM_ALLOC:
242 res = std::make_unique<SharedMemory>();
243 break;
244 case AllocatorType::DMA_ALLOC:
245 res = std::make_unique<DmaMemory>();
246 break;
247 case AllocatorType::CUSTOM_ALLOC:
248 IMAGE_LOGE("MemoryManager::CreateMemory unsupported CUSTOM_ALLOC now");
249 return nullptr;
250 case AllocatorType::DEFAULT:
251 case AllocatorType::HEAP_ALLOC:
252 default:
253 res = std::make_unique<HeapMemory>();
254 break;
255 }
256 if (res == nullptr) {
257 IMAGE_LOGE("MemoryManager::CreateMemory unsupported %{public}d", type);
258 return nullptr;
259 }
260 res->data.data = data.data;
261 res->data.size = data.size;
262 res->data.tag = data.tag;
263 res->data.desiredSize = data.desiredSize;
264 res->data.format = data.format;
265 res->extend.data = extend.data;
266 res->extend.size = extend.size;
267 res->extend.tag = extend.tag;
268 res->extend.desiredSize = extend.desiredSize;
269 res->extend.format = data.format;
270 if (res->data.data == nullptr) {
271 if (res->Create() != SUCCESS) {
272 return nullptr;
273 }
274 }
275 return res;
276 }
277
TransMemoryType(const AbsMemory & source,AllocatorType target,std::string tag)278 std::unique_ptr<AbsMemory> MemoryManager::TransMemoryType(const AbsMemory &source, AllocatorType target,
279 std::string tag)
280 {
281 MemoryData data = { nullptr, source.data.size, tag.c_str()};
282 data.format = source.data.format;
283 auto res = CreateMemory(target, data);
284 if (res == nullptr) {
285 return res;
286 }
287 memcpy_s(res->data.data, res->data.size, source.data.data, source.data.size);
288 return res;
289 }
290 } // namespace Media
291 } // namespace OHOS