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