• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 <memory>
17 #include <sstream>
18 #include <sys/ioctl.h>
19 #include <linux/dma-buf.h>
20 #include "securec.h"
21 #include "avcodec_log.h"
22 #include "avcodec_errors.h"
23 #include "fsurface_memory.h"
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AvCodec-FSurfaceMemory"};
26 #define DMA_BUF_SET_LEAK_TYPE _IOW(DMA_BUF_BASE, 5, const char *)
27 }
28 namespace OHOS {
29 namespace MediaAVCodec {
~FSurfaceMemory()30 FSurfaceMemory::~FSurfaceMemory()
31 {
32     ReleaseSurfaceBuffer();
33 }
34 
AllocSurfaceBuffer(int32_t width,int32_t height)35 int32_t FSurfaceMemory::AllocSurfaceBuffer(int32_t width, int32_t height)
36 {
37     CHECK_AND_RETURN_RET_LOG(sInfo_->surface != nullptr, AVCS_ERR_UNKNOWN, "Surface is nullptr!");
38     CHECK_AND_RETURN_RET_LOG(!isAttached, AVCS_ERR_UNKNOWN, "Only support when not attach!");
39     CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ == nullptr, AVCS_ERR_UNKNOWN, "Surface buffer is not nullptr!");
40     sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
41     CHECK_AND_RETURN_RET_LOG(surfaceBuffer, AVCS_ERR_UNKNOWN, "Create surface buffer failed!");
42     GSError err = surfaceBuffer->Alloc(sInfo_->requestConfig);
43     CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, err, "Alloc surface buffer failed, GSERROR=%{public}d", err);
44     SetSurfaceBuffer(surfaceBuffer, Owner::OWNED_BY_CODEC);
45     isAttached = false;
46     SetCallerToBuffer(width, height);
47     AVCODEC_LOGI("Alloc surface buffer success seq=%{public}u", surfaceBuffer_->GetSeqNum());
48     return AVCS_ERR_OK;
49 }
50 
RequestSurfaceBuffer()51 int32_t FSurfaceMemory::RequestSurfaceBuffer()
52 {
53     CHECK_AND_RETURN_RET_LOG(sInfo_->surface != nullptr, AVCS_ERR_UNKNOWN, "Surface is nullptr");
54     CHECK_AND_RETURN_RET_LOG(owner == Owner::OWNED_BY_SURFACE, AVCS_ERR_UNKNOWN, "Only support when owned by surface!");
55     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
56     auto ret = sInfo_->surface->RequestBuffer(surfaceBuffer, fence_, sInfo_->requestConfig);
57     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK || surfaceBuffer == nullptr) {
58         if (ret != OHOS::SurfaceError::SURFACE_ERROR_NO_BUFFER) {
59             AVCODEC_LOGE("Request surface buffer fail, ret=%{public}" PRIu64, static_cast<uint64_t>(ret));
60         }
61         return ret;
62     }
63     SetSurfaceBuffer(surfaceBuffer, Owner::OWNED_BY_CODEC);
64     return AVCS_ERR_OK;
65 }
66 
ReleaseSurfaceBuffer()67 void FSurfaceMemory::ReleaseSurfaceBuffer()
68 {
69     surfaceBuffer_ = nullptr;
70 }
71 
GetSurfaceBuffer()72 sptr<SurfaceBuffer> FSurfaceMemory::GetSurfaceBuffer()
73 {
74     if (isAttached && owner == Owner::OWNED_BY_SURFACE) {
75         CHECK_AND_RETURN_RET_LOG(RequestSurfaceBuffer() == AVCS_ERR_OK, nullptr, "Get surface buffer failed!");
76     }
77     return surfaceBuffer_;
78 }
79 
SetSurfaceBuffer(sptr<SurfaceBuffer> surfaceBuffer,Owner toChangeOwner)80 void FSurfaceMemory::SetSurfaceBuffer(sptr<SurfaceBuffer> surfaceBuffer, Owner toChangeOwner)
81 {
82     surfaceBuffer_ = surfaceBuffer;
83     owner = toChangeOwner;
84 }
85 
GetSurfaceBufferStride()86 int32_t FSurfaceMemory::GetSurfaceBufferStride()
87 {
88     CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, 0, "Surface buffer is nullptr!");
89     auto bufferHandle = surfaceBuffer_->GetBufferHandle();
90     CHECK_AND_RETURN_RET_LOG(bufferHandle != nullptr, AVCS_ERR_UNKNOWN, "Failed to get bufferHandle!");
91     stride_ = bufferHandle->stride;
92     return stride_;
93 }
94 
GetFence()95 sptr<SyncFence> FSurfaceMemory::GetFence()
96 {
97     return fence_;
98 }
99 
GetBase() const100 uint8_t *FSurfaceMemory::GetBase() const
101 {
102     CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, nullptr, "Surface buffer is nullptr!");
103     return static_cast<uint8_t *>(surfaceBuffer_->GetVirAddr());
104 }
105 
GetSize() const106 int32_t FSurfaceMemory::GetSize() const
107 {
108     CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, -1, "Surface buffer is nullptr!");
109     uint32_t size = surfaceBuffer_->GetSize();
110     return static_cast<int32_t>(size);
111 }
112 
SetCallerToBuffer(int32_t w,int32_t h)113 void FSurfaceMemory::SetCallerToBuffer(int32_t w, int32_t h)
114 {
115     CHECK_AND_RETURN_LOG(surfaceBuffer_ != nullptr, "Surface buffer is nullptr!");
116     int32_t fd = surfaceBuffer_->GetFileDescriptor();
117     CHECK_AND_RETURN_LOG(fd > 0, "Invalid fd %{public}d, surfacebuf(%{public}u)", fd, surfaceBuffer_->GetSeqNum());
118     std::string type = "sw-video-decoder";
119     std::string mime(decInfo_.mimeType);
120     std::vector<std::string> splitMime;
121     std::string token;
122     std::istringstream iss(mime);
123     while (std::getline(iss, token, '/')) {
124         splitMime.push_back(token);
125     }
126     if (!splitMime.empty()) {
127         mime = splitMime.back();
128     }
129     std::string name = std::to_string(w) + "x" + std::to_string(h) + "-" + mime + "-" + decInfo_.instanceId;
130     ioctl(fd, DMA_BUF_SET_LEAK_TYPE, type.c_str());
131     ioctl(fd, DMA_BUF_SET_NAME_A, name.c_str());
132 }
133 } // namespace MediaAVCodec
134 } // namespace OHOS
135