1 /*
2  * Copyright (C) 2023 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 "av_hardware_memory.h"
17 #include "av_shared_memory_ext.h"
18 #include "av_surface_memory.h"
19 #include "av_virtual_memory.h"
20 #include "buffer/avallocator.h"
21 #include "buffer/avbuffer.h"
22 #include "common/log.h"
23 #include "common/status.h"
24 #include "message_parcel.h"
25 #include "securec.h"
26 #include "surface_buffer.h"
27 
28 namespace {
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "AVMemory" };
30 }
31 
32 namespace {
GetUniqueId()33 uint64_t GetUniqueId()
34 {
35 #ifdef MEDIA_OHOS
36     using namespace std::chrono;
37     static const uint64_t startTime =
38         static_cast<uint64_t>(time_point_cast<seconds>(system_clock::now()).time_since_epoch().count());
39     static const uint16_t processId = static_cast<uint16_t>(getpid());
40 #else
41     static const uint64_t startTime = 0;
42     static const uint16_t processId = 0;
43 #endif
44     static std::atomic<uint32_t> bufferId = 0;
45     if (bufferId == UINT32_MAX) {
46         bufferId = 0;
47     }
48     union UniqueId {
49         uint64_t startTime;    //  1--16, 16: time
50         uint16_t processId[4]; // 17--32, 16: process id
51         uint32_t bufferId[2];  // 33--64, 32: atomic val
52     } uid = {.startTime = startTime};
53     ++bufferId;
54     uid.processId[1] = processId;
55     uid.bufferId[1] = bufferId;
56     return uid.startTime;
57 }
58 } // namespace
59 namespace OHOS {
60 namespace Media {
CreateAVMemory(std::shared_ptr<AVAllocator> allocator,int32_t capacity,int32_t align)61 std::shared_ptr<AVMemory> AVMemory::CreateAVMemory(std::shared_ptr<AVAllocator> allocator, int32_t capacity,
62                                                    int32_t align)
63 {
64     MemoryType type = allocator->GetMemoryType();
65     std::shared_ptr<AVMemory> mem = nullptr;
66     switch (type) {
67         case MemoryType::VIRTUAL_MEMORY: {
68             mem = std::shared_ptr<AVMemory>(new AVVirtualMemory());
69             break;
70         }
71         case MemoryType::SURFACE_MEMORY: {
72             mem = std::shared_ptr<AVMemory>(new AVSurfaceMemory());
73             break;
74         }
75         case MemoryType::SHARED_MEMORY: {
76             mem = std::shared_ptr<AVMemory>(new AVSharedMemoryExt());
77             break;
78         }
79         case MemoryType::HARDWARE_MEMORY: {
80             mem = std::shared_ptr<AVMemory>(new AVHardwareMemory());
81             break;
82         }
83         default:
84             break;
85     }
86     FALSE_RETURN_V_MSG_E(mem != nullptr, nullptr, "Create AVMemory failed, no memory");
87 
88     mem->allocator_ = allocator;
89     mem->capacity_ = capacity;
90     mem->align_ = align;
91     Status ret = mem->Init();
92     FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Init AVMemory failed, uid:" PUBLIC_LOG_U64, mem->uid_);
93     return mem;
94 }
95 
CreateAVMemory(uint8_t * ptr,int32_t capacity,int32_t size)96 std::shared_ptr<AVMemory> AVMemory::CreateAVMemory(uint8_t *ptr, int32_t capacity, int32_t size)
97 {
98     std::shared_ptr<AVMemory> mem = std::shared_ptr<AVMemory>(new AVVirtualMemory());
99     FALSE_RETURN_V_MSG_E(mem != nullptr, nullptr, "Create AVVirtualMemory failed, no memory");
100     mem->allocator_ = nullptr;
101     mem->capacity_ = capacity;
102     mem->size_ = size;
103     mem->base_ = ptr;
104     return mem;
105 }
106 
CreateAVMemory(MessageParcel & parcel,bool isSurfaceBuffer)107 std::shared_ptr<AVMemory> AVMemory::CreateAVMemory(MessageParcel &parcel, bool isSurfaceBuffer)
108 {
109 #ifdef MEDIA_OHOS
110     if (isSurfaceBuffer) {
111         auto mem = std::shared_ptr<AVMemory>(new AVSurfaceMemory());
112         Status ret = mem->InitSurfaceBuffer(parcel);
113         FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Init AVSurfaceMemory failed");
114         return mem;
115     }
116     MemoryType type = static_cast<MemoryType>(parcel.ReadUint8());
117     std::shared_ptr<AVMemory> mem = nullptr;
118     switch (type) {
119         case MemoryType::VIRTUAL_MEMORY: {
120             return nullptr;
121         }
122         case MemoryType::SURFACE_MEMORY: {
123             mem = std::shared_ptr<AVMemory>(new AVSurfaceMemory());
124             break;
125         }
126         case MemoryType::SHARED_MEMORY: {
127             mem = std::shared_ptr<AVMemory>(new AVSharedMemoryExt());
128             break;
129         }
130         case MemoryType::HARDWARE_MEMORY: {
131             mem = std::shared_ptr<AVMemory>(new AVHardwareMemory());
132             break;
133         }
134         default:
135             break;
136     }
137 
138     FALSE_RETURN_V_MSG_E(mem != nullptr, nullptr, "Create AVMemory failed, no memory");
139     bool isReadParcel = mem->ReadCommonFromMessageParcel(parcel);
140     FALSE_RETURN_V_MSG_E(isReadParcel == true, nullptr, "Read common memory info from parcel failed");
141 
142     Status ret = mem->Init(parcel);
143     FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Init AVMemory failed, uid:" PUBLIC_LOG_U64, mem->uid_);
144     return mem;
145 #else
146     return nullptr;
147 #endif
148 }
149 
CreateAVMemory(sptr<SurfaceBuffer> surfaceBuffer)150 std::shared_ptr<AVMemory> AVMemory::CreateAVMemory(sptr<SurfaceBuffer> surfaceBuffer)
151 {
152     auto mem = std::shared_ptr<AVMemory>(new AVSurfaceMemory());
153     Status ret = mem->InitSurfaceBuffer(surfaceBuffer);
154     FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "Init AVSurfaceMemory failed");
155     return mem;
156 }
157 
AVMemory()158 AVMemory::AVMemory() : align_(0), offset_(0), size_(0), base_(nullptr), uid_(GetUniqueId()), allocator_(nullptr)
159 {
160     MEDIA_LOG_DD("enter ctor, instance:0x%{public}06" PRIXPTR ", uid:" PUBLIC_LOG_U64, FAKE_POINTER(this), uid_);
161 }
162 
~AVMemory()163 AVMemory::~AVMemory()
164 {
165     MEDIA_LOG_DD("enter dtor, instance:0x%{public}06" PRIXPTR ", uid:" PUBLIC_LOG_U64, FAKE_POINTER(this), uid_);
166 }
167 
Init()168 Status AVMemory::Init()
169 {
170     return Status::ERROR_UNIMPLEMENTED;
171 }
172 
Init(MessageParcel & parcel)173 Status AVMemory::Init(MessageParcel &parcel)
174 {
175     (void)parcel;
176     return Status::ERROR_UNIMPLEMENTED;
177 }
178 
InitSurfaceBuffer(MessageParcel & parcel)179 Status AVMemory::InitSurfaceBuffer(MessageParcel &parcel)
180 {
181     (void)parcel;
182     return Status::ERROR_UNIMPLEMENTED;
183 }
184 
InitSurfaceBuffer(sptr<SurfaceBuffer> surfaceBuffer)185 Status AVMemory::InitSurfaceBuffer(sptr<SurfaceBuffer> surfaceBuffer)
186 {
187     (void)surfaceBuffer;
188     return Status::ERROR_UNIMPLEMENTED;
189 }
190 
ReadFromMessageParcel(MessageParcel & parcel)191 bool AVMemory::ReadFromMessageParcel(MessageParcel &parcel)
192 {
193     (void)parcel;
194     return false;
195 }
196 
WriteToMessageParcel(MessageParcel & parcel)197 bool AVMemory::WriteToMessageParcel(MessageParcel &parcel)
198 {
199     (void)parcel;
200     return false;
201 }
202 
ReadCommonFromMessageParcel(MessageParcel & parcel)203 bool AVMemory::ReadCommonFromMessageParcel(MessageParcel &parcel)
204 {
205 #ifdef MEDIA_OHOS
206     (void)parcel.ReadUint64();
207     int32_t capacity = -1;
208     int32_t align = -1;
209     int32_t offset = -1;
210     int32_t size = -1;
211 
212     bool ret = parcel.ReadInt32(capacity);
213     FALSE_RETURN_V_MSG_E(ret && (capacity >= 0), false, "capacity is invalid");
214 
215     ret = parcel.ReadInt32(align);
216     FALSE_RETURN_V_MSG_E(ret && (capacity >= align) && (align >= 0), false, "align is invalid");
217 
218     ret = parcel.ReadInt32(offset);
219     FALSE_RETURN_V_MSG_E(ret && (capacity >= offset) && (offset >= 0), false, "offset is invalid");
220 
221     ret = parcel.ReadInt32(size);
222     FALSE_RETURN_V_MSG_E(ret && (capacity >= size) && (size >= 0), false, "size is invalid");
223 
224     capacity_ = capacity;
225     align_ = align;
226     offset_ = offset;
227     size_ = size;
228     return true;
229 #else
230     return true;
231 #endif
232 }
233 
SkipCommonFromMessageParcel(MessageParcel & parcel)234 bool AVMemory::SkipCommonFromMessageParcel(MessageParcel &parcel)
235 {
236 #ifdef MEDIA_OHOS
237     uint64_t skipSize = 0;
238     bool ret = parcel.ReadUint64(skipSize);
239     FALSE_RETURN_V_MSG_E(ret, false, "unknown parcel");
240     parcel.SkipBytes(static_cast<size_t>(skipSize) - 2 * sizeof(int32_t)); // 2: the size of size_ and offset_
241 
242     int32_t size = -1;
243     int32_t offset = -1;
244 
245     ret = parcel.ReadInt32(offset);
246     FALSE_RETURN_V_MSG_E(ret && (capacity_ >= offset) && (offset >= 0), false, "offset is invalid");
247 
248     ret = parcel.ReadInt32(size);
249     FALSE_RETURN_V_MSG_E(ret && (capacity_ >= size) && (size >= 0), false, "size is invalid");
250 
251     size_ = size;
252     offset_ = offset;
253     return true;
254 #else
255     return true;
256 #endif
257 }
258 
WriteCommonToMessageParcel(MessageParcel & parcel)259 bool AVMemory::WriteCommonToMessageParcel(MessageParcel &parcel)
260 {
261 #ifdef MEDIA_OHOS
262     bool ret = true;
263     MessageParcel bufferParcel;
264     ret = bufferParcel.WriteInt32(capacity_) && bufferParcel.WriteInt32(align_) && bufferParcel.WriteInt32(offset_) &&
265           bufferParcel.WriteInt32(size_);
266 
267     size_t size = bufferParcel.GetDataSize();
268     return ret && parcel.WriteUint64(static_cast<uint64_t>(size)) && parcel.Append(bufferParcel);
269 #endif
270     return true;
271 }
272 
GetMemoryType()273 MemoryType AVMemory::GetMemoryType()
274 {
275     return MemoryType::VIRTUAL_MEMORY;
276 }
277 
GetMemoryFlag()278 MemoryFlag AVMemory::GetMemoryFlag()
279 {
280     return MemoryFlag::MEMORY_READ_WRITE;
281 }
282 
GetCapacity()283 int32_t AVMemory::GetCapacity()
284 {
285     return capacity_;
286 }
287 
GetSize()288 int32_t AVMemory::GetSize()
289 {
290     return size_;
291 }
292 
SetSize(int32_t size)293 Status AVMemory::SetSize(int32_t size)
294 {
295     FALSE_RETURN_V_MSG_E((capacity_ >= size) && (size >= 0), Status::ERROR_INVALID_PARAMETER,
296                          "size out of range, "
297                          "current size:%{public}d , capacity:%{public}d",
298                          size_, capacity_);
299     size_ = size;
300     return Status::OK;
301 }
302 
GetOffset()303 int32_t AVMemory::GetOffset()
304 {
305     return offset_;
306 }
307 
SetOffset(int32_t offset)308 Status AVMemory::SetOffset(int32_t offset)
309 {
310     FALSE_RETURN_V_MSG_E((capacity_ >= offset) && (offset >= 0), Status::ERROR_INVALID_PARAMETER,
311                          "offset out of range, "
312                          "current offset:%{public}d , capacity:%{public}d",
313                          offset_, capacity_);
314     offset_ = offset;
315     return Status::OK;
316 }
317 
GetAddr()318 uint8_t *AVMemory::GetAddr()
319 {
320     return base_;
321 }
322 
GetFileDescriptor()323 int32_t AVMemory::GetFileDescriptor()
324 {
325     return -1;
326 }
327 
Write(const uint8_t * in,int32_t writeSize,int32_t position)328 int32_t AVMemory::Write(const uint8_t *in, int32_t writeSize, int32_t position)
329 {
330     FALSE_RETURN_V_MSG_E(in != nullptr, 0, "Input buffer is nullptr");
331     FALSE_RETURN_V_MSG_E(writeSize > 0, 0, "Input writeSize:%{public}d is invalid", writeSize);
332     FALSE_RETURN_V_MSG_E((GetMemoryFlag() & MemoryFlag::MEMORY_WRITE_ONLY) != 0, 0, "Lack write permission");
333     uint8_t *addr = GetAddr();
334     FALSE_RETURN_V_MSG_E(addr != nullptr, 0, "Base buffer is nullptr");
335     int32_t start = 0;
336     if (position <= INVALID_POSITION) {
337         start = size_;
338     } else {
339         start = std::min(position, capacity_);
340     }
341     int32_t unusedSize = capacity_ - start;
342     int32_t length = std::min(writeSize, unusedSize);
343     FALSE_RETURN_V_MSG_E((length + start) <= capacity_, 0,
344                          "Write out of bounds, length:%{public}d , start:%{public}d , capacity:%{public}d", length,
345                          start, capacity_);
346     uint8_t *dstPtr = addr + start;
347     FALSE_RETURN_V_MSG_E(dstPtr != nullptr, 0, "Inner dstPtr is nullptr");
348     auto error = memcpy_s(dstPtr, length, in, length);
349     FALSE_RETURN_V_MSG_E(error == EOK, 0, "Inner memcpy_s failed, uid:" PUBLIC_LOG_U64 ", %{public}s", uid_,
350                          strerror(error));
351     size_ = start + length;
352     return length;
353 }
354 
Read(uint8_t * out,int32_t readSize,int32_t position)355 int32_t AVMemory::Read(uint8_t *out, int32_t readSize, int32_t position)
356 {
357     FALSE_RETURN_V_MSG_E(out != nullptr, 0, "Output buffer is nullptr");
358     FALSE_RETURN_V_MSG_E(readSize > 0, 0, "Output readSize:%{public}d is invalid", readSize);
359     FALSE_RETURN_V_MSG_E((GetMemoryFlag() & MemoryFlag::MEMORY_READ_ONLY) != 0, 0, "Lack read permission");
360     uint8_t *addr = GetAddr();
361     FALSE_RETURN_V_MSG_E(addr != nullptr, 0, "Base buffer is nullptr");
362     int32_t start = 0;
363     int32_t maxLength = size_;
364     if (position > INVALID_POSITION) {
365         start = std::min(position, size_);
366         maxLength = size_ - start;
367     }
368     int32_t length = std::min(readSize, maxLength);
369     FALSE_RETURN_V_MSG_E((length + start) <= capacity_, 0,
370                          "Read out of bounds, length:%{public}d, start:%{public}d, capacity:%{public}d", length, start,
371                          capacity_);
372     uint8_t *srcPtr = addr + start;
373     FALSE_RETURN_V_MSG_E(srcPtr != nullptr, 0, "Inner srcPtr is nullptr");
374     auto error = memcpy_s(out, length, srcPtr, length);
375     FALSE_RETURN_V_MSG_E(error == EOK, 0, "Inner memcpy_s failed, uid:%" PUBLIC_LOG_U64 ", %{public}s", uid_,
376                          strerror(error));
377     return length;
378 }
379 
Reset()380 void AVMemory::Reset()
381 {
382     size_ = 0;
383 }
384 
GetSurfaceBuffer()385 sptr<SurfaceBuffer> AVMemory::GetSurfaceBuffer()
386 {
387     return nullptr;
388 }
389 } // namespace Media
390 } // namespace OHOS