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