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