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