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 if (sb == nullptr) {
184 IMAGE_LOGE("SurfaceBuffer failed to be created");
185 return ERR_DMA_DATA_ABNORMAL;
186 }
187 GraphicPixelFormat format = GetRequestBufferFormatWithPixelFormat(data.format);
188 BufferRequestConfig requestConfig = {
189 .width = data.desiredSize.width,
190 .height = data.desiredSize.height,
191 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
192 .format = format, // PixelFormat
193 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
194 .timeout = 0,
195 };
196 GSError ret = sb->Alloc(requestConfig);
197 if (ret != GSERROR_OK) {
198 IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
199 return ERR_DMA_NOT_EXIST;
200 }
201 void* nativeBuffer = sb.GetRefPtr();
202 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
203 if (err != OHOS::GSERROR_OK) {
204 IMAGE_LOGE("NativeBufferReference failed");
205 return ERR_DMA_DATA_ABNORMAL;
206 }
207 data.data = static_cast<uint8_t*>(sb->GetVirAddr());
208 extend.size = data.size;
209 extend.data = nativeBuffer;
210 return SUCCESS;
211 #endif
212 }
213
Release()214 uint32_t DmaMemory::Release()
215 {
216 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
217 IMAGE_LOGE("Unsupport dma mem release");
218 return ERR_IMAGE_DATA_UNSUPPORT;
219 #else
220 data.data = nullptr;
221 data.size = SIZE_ZERO;
222 if (extend.data != nullptr) {
223 int32_t err = ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(extend.data));
224 if (err != OHOS::GSERROR_OK) {
225 IMAGE_LOGE("NativeBufferReference failed");
226 extend.data = nullptr;
227 extend.size = SIZE_ZERO;
228 return ERR_DMA_DATA_ABNORMAL;
229 }
230 extend.data = nullptr;
231 extend.size = SIZE_ZERO;
232 }
233 return SUCCESS;
234 #endif
235 }
236
CreateMemory(AllocatorType type,MemoryData & data)237 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data)
238 {
239 MemoryData extend{};
240 return CreateMemory(type, data, extend);
241 }
242
CreateMemory(AllocatorType type,MemoryData & data,MemoryData & extend)243 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data, MemoryData &extend)
244 {
245 std::unique_ptr<AbsMemory> res = nullptr;
246 switch (type) {
247 case AllocatorType::SHARE_MEM_ALLOC:
248 res = std::make_unique<SharedMemory>();
249 break;
250 case AllocatorType::DMA_ALLOC:
251 res = std::make_unique<DmaMemory>();
252 break;
253 case AllocatorType::CUSTOM_ALLOC:
254 IMAGE_LOGE("MemoryManager::CreateMemory unsupported CUSTOM_ALLOC now");
255 return nullptr;
256 case AllocatorType::DEFAULT:
257 case AllocatorType::HEAP_ALLOC:
258 default:
259 res = std::make_unique<HeapMemory>();
260 break;
261 }
262 if (res == nullptr) {
263 IMAGE_LOGE("MemoryManager::CreateMemory unsupported %{public}d", type);
264 return nullptr;
265 }
266 res->data.data = data.data;
267 res->data.size = data.size;
268 res->data.tag = data.tag;
269 res->data.desiredSize = data.desiredSize;
270 res->data.format = data.format;
271 res->extend.data = extend.data;
272 res->extend.size = extend.size;
273 res->extend.tag = extend.tag;
274 res->extend.desiredSize = extend.desiredSize;
275 res->extend.format = data.format;
276 if (res->data.data == nullptr) {
277 if (res->Create() != SUCCESS) {
278 return nullptr;
279 }
280 }
281 return res;
282 }
283 } // namespace Media
284 } // namespace OHOS