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