/* * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "av_surface_memory.h" #include #include "av_surface_allocator.h" #include "common/log.h" #include "common/status.h" #include "message_parcel.h" #include "scope_guard.h" #include "surface_buffer.h" #include "surface_type.h" namespace OHOS { namespace Media { std::shared_ptr AVAllocatorFactory::CreateSurfaceAllocator(const BufferRequestConfig &config) { auto allocator = std::shared_ptr(new AVSurfaceAllocator()); FALSE_RETURN_V_MSG_E(allocator != nullptr, nullptr, "Create AVSurfaceAllocator failed, no memory"); allocator->config_ = config; return allocator; } AVSurfaceAllocator::AVSurfaceAllocator() {} void *AVSurfaceAllocator::Alloc(int32_t capacity) { (void)capacity; sptr surfaceBuffer = SurfaceBuffer::Create(); FALSE_RETURN_V_MSG_E(surfaceBuffer != nullptr, nullptr, "No memory for new SurfaceBuffer!"); GSError ret = surfaceBuffer->Alloc(config_); FALSE_RETURN_V_MSG_E(ret == GSERROR_OK, nullptr, "Surface Buffer Alloc failed, %{public}s", GSErrorStr(ret).c_str()); surfaceBuffer->IncStrongRef(surfaceBuffer.GetRefPtr()); return static_cast(surfaceBuffer.GetRefPtr()); } bool AVSurfaceAllocator::Free(void *ptr) { FALSE_RETURN_V_MSG_E(ptr != nullptr, false, "ptr is nullptr"); sptr surfaceBuffer = sptr(static_cast(ptr)); surfaceBuffer->DecStrongRef(surfaceBuffer.GetRefPtr()); MEDIA_LOG_DD("GetSptrRefCount:%{public}d", surfaceBuffer->GetSptrRefCount()); surfaceBuffer = nullptr; return true; } MemoryType AVSurfaceAllocator::GetMemoryType() { return MemoryType::SURFACE_MEMORY; } AVSurfaceMemory::AVSurfaceMemory() : isFirstFlag_(true) {} AVSurfaceMemory::~AVSurfaceMemory() { if (base_ != nullptr) { surfaceBuffer_->Unmap(); base_ = nullptr; } if (allocator_ != nullptr) { bool ret = allocator_->Free(surfaceBuffer_.GetRefPtr()); FALSE_RETURN_MSG(ret, "Free memory failed, instance: 0x%{public}06" PRIXPTR, FAKE_POINTER(this)); } surfaceBuffer_ = nullptr; } Status AVSurfaceMemory::Init() { surfaceBuffer_ = sptr(static_cast(allocator_->Alloc(0))); FALSE_RETURN_V_MSG_E(surfaceBuffer_ != nullptr, Status::ERROR_NO_MEMORY, "surfaceBuffer_ alloc failed"); capacity_ = surfaceBuffer_->GetSize(); return Status::OK; } Status AVSurfaceMemory::Init(MessageParcel &parcel) { (void)parcel.ReadUint64(); return InitSurfaceBuffer(parcel); } Status AVSurfaceMemory::InitSurfaceBuffer(MessageParcel &parcel) { surfaceBuffer_ = SurfaceBuffer::Create(); FALSE_RETURN_V_MSG_E(surfaceBuffer_ != nullptr, Status::ERROR_NO_MEMORY, "No memory for new SurfaceBuffer!"); GSError ret = surfaceBuffer_->ReadFromMessageParcel(parcel); FALSE_RETURN_V_MSG_E(ret == GSERROR_OK, Status::ERROR_INVALID_OPERATION, "Read message parcel failed! %{public}s", GSErrorStr(ret).c_str()); capacity_ = surfaceBuffer_->GetSize(); return Status::OK; } Status AVSurfaceMemory::InitSurfaceBuffer(sptr surfaceBuffer) { surfaceBuffer_ = surfaceBuffer; capacity_ = surfaceBuffer_->GetSize(); return Status::OK; } bool AVSurfaceMemory::WriteToMessageParcel(MessageParcel &parcel) { #ifdef MEDIA_OHOS MessageParcel bufferParcel; GSError gsRet = surfaceBuffer_->WriteToMessageParcel(bufferParcel); FALSE_RETURN_V_MSG_E(gsRet == GSERROR_OK, false, "Write message parcel failed!, %{public}s", GSErrorStr(gsRet).c_str()); size_t size = bufferParcel.GetDataSize(); return parcel.WriteUint64(static_cast(size)) && parcel.Append(bufferParcel); #else return true; #endif } bool AVSurfaceMemory::ReadFromMessageParcel(MessageParcel &parcel) { #ifdef MEDIA_OHOS uint64_t size = 0; bool ret = parcel.ReadUint64(size); parcel.SkipBytes(static_cast(size)); return ret; #else return true; #endif } uint8_t *AVSurfaceMemory::GetAddr() { if (isFirstFlag_) { Status ret = MapMemoryAddr(); FALSE_RETURN_V_MSG_E(ret == Status::OK, nullptr, "MapMemory failed"); isFirstFlag_ = false; } return base_; } MemoryType AVSurfaceMemory::GetMemoryType() { return MemoryType::SURFACE_MEMORY; } int32_t AVSurfaceMemory::GetFileDescriptor() { return surfaceBuffer_->GetFileDescriptor(); } sptr AVSurfaceMemory::GetSurfaceBuffer() { return surfaceBuffer_; } void AVSurfaceMemory::UnMapMemoryAddr() { if (base_ != nullptr) { surfaceBuffer_->Unmap(); base_ = nullptr; } } Status AVSurfaceMemory::MapMemoryAddr() { ON_SCOPE_EXIT(0) { MEDIA_LOG_E("create avsurfacememory failed, uid:" PUBLIC_LOG_U64 ", capacity:%{public}d", uid_, capacity_); UnMapMemoryAddr(); return Status::ERROR_NO_MEMORY; }; GSError ret = surfaceBuffer_->Map(); FALSE_RETURN_V_MSG_E(ret == GSERROR_OK, Status::ERROR_INVALID_OPERATION, "mmap failed, please check params, %{public}s", GSErrorStr(ret).c_str()); base_ = reinterpret_cast(surfaceBuffer_->GetVirAddr()); CANCEL_SCOPE_EXIT_GUARD(0); return Status::OK; } } // namespace Media } // namespace OHOS