• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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