• 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 "hilog/log.h"
21 #include "image_utils.h"
22 #include "log_tags.h"
23 #include "media_errors.h"
24 #include "securec.h"
25 
26 #if !defined(_WIN32) && !defined(_APPLE) &&!defined(IOS_PLATFORM) &&!defined(A_PLATFORM)
27 #include <sys/mman.h>
28 #include "ashmem.h"
29 #include "surface_buffer.h"
30 #define SUPPORT_SHARED_MEMORY
31 #endif
32 
33 namespace OHOS {
34 namespace Media {
35 using namespace OHOS::HiviewDFX;
36 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "MemoryManager" };
37 static const size_t SIZE_ZERO = 0;
38 static const int LINUX_SUCCESS = 0;
39 // Define pixel map malloc max size 600MB
40 constexpr int32_t PIXEL_MAP_MAX_RAM_SIZE = 600 * 1024 * 1024;
41 
Create()42 uint32_t HeapMemory::Create()
43 {
44     HiLog::Debug(LABEL, "HeapMemory::Create IN");
45     if (data.data != nullptr) {
46         HiLog::Debug(LABEL, "HeapMemory::Create has created");
47         return SUCCESS;
48     }
49     if (data.size == 0 || data.size > PIXEL_MAP_MAX_RAM_SIZE) {
50         HiLog::Error(LABEL, "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         HiLog::Error(LABEL, "HeapMemory::Create malloc buffer failed");
56         return ERR_IMAGE_MALLOC_ABNORMAL;
57     }
58 #if defined(IOS_PLATFORM) || defined(A_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(A_PLATFORM)
67     HiLog::Debug(LABEL, "HeapMemory::Release IN");
68     if (data.data == nullptr) {
69         HiLog::Error(LABEL, "HeapMemory::Release nullptr data");
70         return ERR_IMAGE_DATA_ABNORMAL;
71     }
72     free(data.data);
73     data.data = nullptr;
74 #endif
75     return SUCCESS;
76 }
77 
ReleaseSharedMemory(int * fdPtr,uint8_t * ptr=nullptr,size_t size=SIZE_ZERO)78 static inline void ReleaseSharedMemory(int* fdPtr, uint8_t* ptr = nullptr, size_t size = SIZE_ZERO)
79 {
80 #if !defined(IOS_PLATFORM) &&!defined(A_PLATFORM)
81     if (ptr != nullptr && ptr != MAP_FAILED) {
82         ::munmap(ptr, size);
83     }
84     if (fdPtr != nullptr) {
85         ::close(*fdPtr);
86     }
87 #endif
88 }
89 
Create()90 uint32_t SharedMemory::Create()
91 {
92 #ifdef SUPPORT_SHARED_MEMORY
93     HiLog::Debug(LABEL, "SharedMemory::Create IN tag %{public}s, data size %{public}zu",
94         (data.tag == nullptr)?"nullptr":data.tag, data.size);
95 
96     if (data.tag == nullptr || data.size == SIZE_ZERO) {
97         HiLog::Error(LABEL, "SharedMemory::Create tag is nullptr or data size %{public}zu", data.size);
98         return ERR_IMAGE_DATA_ABNORMAL;
99     }
100     auto fdPtr = std::make_unique<int>();
101     *fdPtr = AshmemCreate(data.tag, data.size);
102     if (*fdPtr < 0) {
103         HiLog::Error(LABEL, "SharedMemory::Create AshmemCreate fd:[%{public}d].", *fdPtr);
104         return ERR_IMAGE_DATA_ABNORMAL;
105     }
106     if (AshmemSetProt(*fdPtr, PROT_READ | PROT_WRITE) < LINUX_SUCCESS) {
107         HiLog::Error(LABEL, "SharedMemory::Create AshmemSetProt errno %{public}d.", errno);
108         ReleaseSharedMemory(fdPtr.get());
109         return ERR_IMAGE_DATA_ABNORMAL;
110     }
111     data.data = ::mmap(nullptr, data.size, PROT_READ | PROT_WRITE, MAP_SHARED, *fdPtr, 0);
112     if (data.data == MAP_FAILED) {
113         HiLog::Error(LABEL, "SharedMemory::Create mmap failed, errno:%{public}d", errno);
114         ReleaseSharedMemory(fdPtr.get(), static_cast<uint8_t*>(data.data), data.size);
115         return ERR_IMAGE_DATA_ABNORMAL;
116     }
117     extend.size = sizeof(int);
118     extend.data = fdPtr.release();
119     return SUCCESS;
120 #else
121     HiLog::Error(LABEL, "SharedMemory::Create unsupported");
122     return ERR_IMAGE_DATA_UNSUPPORT;
123 #endif
124 }
125 
Release()126 uint32_t SharedMemory::Release()
127 {
128 #ifdef SUPPORT_SHARED_MEMORY
129     HiLog::Debug(LABEL, "SharedMemory::Release IN");
130     ReleaseSharedMemory(static_cast<int*>(extend.data), static_cast<uint8_t*>(data.data), data.size);
131     data.data = nullptr;
132     data.size = SIZE_ZERO;
133     if (extend.data != nullptr) {
134         free(extend.data);
135         extend.data = nullptr;
136         extend.size = SIZE_ZERO;
137     }
138     return SUCCESS;
139 #else
140     HiLog::Error(LABEL, "SharedMemory::Release unsupported");
141     return ERR_IMAGE_DATA_UNSUPPORT;
142 #endif
143 }
144 
Create()145 uint32_t DmaMemory::Create()
146 {
147 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
148     HiLog::Error(LABEL, "Unsupport dma mem alloc");
149     return ERR_IMAGE_DATA_UNSUPPORT;
150 #else
151     sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
152     BufferRequestConfig requestConfig = {
153         .width = data.desiredSize.width,
154         .height = data.desiredSize.height,
155         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
156         .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
157         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
158         .timeout = 0,
159         .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
160         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
161     };
162     GSError ret = sb->Alloc(requestConfig);
163     if (ret != GSERROR_OK) {
164         HiLog::Error(LABEL, "SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
165         return ERR_DMA_NOT_EXIST;
166     }
167     void* nativeBuffer = sb.GetRefPtr();
168     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
169     if (err != OHOS::GSERROR_OK) {
170         HiLog::Error(LABEL, "NativeBufferReference failed");
171         return ERR_DMA_DATA_ABNORMAL;
172     }
173     data.data = static_cast<uint8_t*>(sb->GetVirAddr());
174     extend.size = data.size;
175     extend.data = nativeBuffer;
176     return SUCCESS;
177 #endif
178 }
179 
Release()180 uint32_t DmaMemory::Release()
181 {
182 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
183     HiLog::Error(LABEL, "Unsupport dma mem release");
184     return ERR_IMAGE_DATA_UNSUPPORT;
185 #else
186     data.data = nullptr;
187     data.size = SIZE_ZERO;
188     if (extend.data != nullptr) {
189         int32_t err = ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(extend.data));
190         if (err != OHOS::GSERROR_OK) {
191             HiLog::Error(LABEL, "NativeBufferReference failed");
192             return ERR_DMA_DATA_ABNORMAL;
193         }
194         extend.data = nullptr;
195         extend.size = SIZE_ZERO;
196     }
197     return SUCCESS;
198 #endif
199 }
200 
CreateMemory(AllocatorType type,MemoryData & data)201 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data)
202 {
203     MemoryData extend;
204     return CreateMemory(type, data, extend);
205 }
206 
CreateMemory(AllocatorType type,MemoryData & data,MemoryData & extend)207 std::unique_ptr<AbsMemory> MemoryManager::CreateMemory(AllocatorType type, MemoryData &data, MemoryData &extend)
208 {
209     std::unique_ptr<AbsMemory> res = nullptr;
210     switch (type) {
211         case AllocatorType::SHARE_MEM_ALLOC:
212             res = std::make_unique<SharedMemory>();
213             break;
214         case AllocatorType::DMA_ALLOC:
215             res = std::make_unique<DmaMemory>();
216             break;
217         case AllocatorType::CUSTOM_ALLOC:
218             HiLog::Error(LABEL, "MemoryManager::CreateMemory unsupported CUSTOM_ALLOC now");
219             return nullptr;
220         case AllocatorType::DEFAULT:
221         case AllocatorType::HEAP_ALLOC:
222         default:
223             res = std::make_unique<HeapMemory>();
224             break;
225     }
226     if (res == nullptr) {
227         HiLog::Error(LABEL, "MemoryManager::CreateMemory unsupported %{public}d", type);
228         return nullptr;
229     }
230     res->data.data = data.data;
231     res->data.size = data.size;
232     res->data.tag = data.tag;
233     res->data.desiredSize = data.desiredSize;
234     res->extend.data = extend.data;
235     res->extend.size = extend.size;
236     res->extend.tag = extend.tag;
237     res->extend.desiredSize = extend.desiredSize;
238     if (res->data.data == nullptr) {
239         if (res->Create() != SUCCESS) {
240             return nullptr;
241         }
242     }
243     return res;
244 }
245 
TransMemoryType(const AbsMemory & source,AllocatorType target,std::string tag)246 std::unique_ptr<AbsMemory> MemoryManager::TransMemoryType(const AbsMemory &source, AllocatorType target,
247     std::string tag)
248 {
249     MemoryData data = { nullptr, source.data.size, tag.c_str()};
250     auto res = CreateMemory(target, data);
251     if (res == nullptr) {
252         return res;
253     }
254     memcpy_s(res->data.data, res->data.size, source.data.data, source.data.size);
255     return res;
256 }
257 } // namespace Media
258 } // namespace OHOS