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