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 "securec.h"
18 #include "avcodec_log.h"
19 #include "avcodec_errors.h"
20 #include "surface_memory.h"
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AvCodec-SurfaceMemory"};
23 }
24 namespace OHOS {
25 namespace MediaAVCodec {
26 sptr<Surface> SurfaceMemory::surface_ = nullptr;
27 BufferRequestConfig SurfaceMemory::requestConfig_ = {0};
28 ScalingMode SurfaceMemory::scalingMode_ = {ScalingMode::SCALING_MODE_SCALE_TO_WINDOW};
29
Create()30 std::shared_ptr<SurfaceMemory> SurfaceMemory::Create()
31 {
32 CHECK_AND_RETURN_RET_LOG(surface_ != nullptr, nullptr, "surface is nullptr");
33 CHECK_AND_RETURN_RET_LOG(requestConfig_.width != 0 && requestConfig_.height != 0, nullptr,
34 "surface config invalid");
35 std::shared_ptr<SurfaceMemory> buffer = std::make_shared<SurfaceMemory>();
36 buffer->AllocSurfaceBuffer();
37 return buffer;
38 }
39
~SurfaceMemory()40 SurfaceMemory::~SurfaceMemory()
41 {
42 ReleaseSurfaceBuffer();
43 }
44
Write(const uint8_t * in,int32_t writeSize,int32_t position)45 int32_t SurfaceMemory::Write(const uint8_t *in, int32_t writeSize, int32_t position)
46 {
47 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, 0, "surfaceBuffer is nullptr");
48 int32_t start = 0;
49 int32_t capacity = GetSize();
50 if (position == INVALID_POSITION) {
51 start = size_;
52 } else {
53 start = std::min(position, capacity);
54 }
55 int32_t length = std::min(writeSize, capacity - start);
56 if (memcpy_s(GetBase() + start, length, in, length) != EOK) {
57 return 0;
58 }
59 size_ = start + length;
60 return length;
61 }
62
Read(uint8_t * out,int32_t readSize,int32_t position)63 int32_t SurfaceMemory::Read(uint8_t *out, int32_t readSize, int32_t position)
64 {
65 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, 0, "surfaceBuffer is nullptr");
66 int32_t start = 0;
67 int32_t maxLength = size_;
68 if (position != INVALID_POSITION) {
69 start = std::min(position, size_);
70 maxLength = size_ - start;
71 }
72 int32_t length = std::min(readSize, maxLength);
73 if (memcpy_s(out, length, GetBase() + start, length) != EOK) {
74 return 0;
75 }
76 return length;
77 }
78
AllocSurfaceBuffer()79 void SurfaceMemory::AllocSurfaceBuffer()
80 {
81 if (surface_ == nullptr || surfaceBuffer_ != nullptr) {
82 AVCODEC_LOGE("surface is nullptr or surfaceBuffer is not nullptr");
83 return;
84 }
85 fence_ = -1;
86 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
87 auto ret = surface_->RequestBuffer(surfaceBuffer, fence_, requestConfig_);
88 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK || surfaceBuffer == nullptr) {
89 if (ret == OHOS::SurfaceError::SURFACE_ERROR_NO_BUFFER) {
90 AVCODEC_LOGD("buffer queue is no more buffers");
91 } else {
92 AVCODEC_LOGE("surface RequestBuffer fail, ret: %{public}" PRIu64, static_cast<uint64_t>(ret));
93 }
94 return;
95 }
96
97 surfaceBuffer_ = surfaceBuffer;
98 AVCODEC_LOGD("request surface buffer success, releaseFence: %{public}d", fence_);
99 }
100
ReleaseSurfaceBuffer()101 void SurfaceMemory::ReleaseSurfaceBuffer()
102 {
103 if (surfaceBuffer_ == nullptr) {
104 return;
105 }
106 if (!needRender_) {
107 auto ret = surface_->CancelBuffer(surfaceBuffer_);
108 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
109 AVCODEC_LOGE("surface CancelBuffer fail, ret: %{public}" PRIu64, static_cast<uint64_t>(ret));
110 }
111 }
112 surfaceBuffer_ = nullptr;
113 }
114
GetSurfaceBuffer()115 sptr<SurfaceBuffer> SurfaceMemory::GetSurfaceBuffer()
116 {
117 if (!surfaceBuffer_) {
118 // request surface buffer again when old buffer flush to nullptr
119 AllocSurfaceBuffer();
120 }
121 return surfaceBuffer_;
122 }
123
GetSurfaceBufferStride()124 int32_t SurfaceMemory::GetSurfaceBufferStride()
125 {
126 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, 0, "surfaceBuffer is nullptr");
127 auto bufferHandle = surfaceBuffer_->GetBufferHandle();
128 if (bufferHandle == nullptr) {
129 AVCODEC_LOGE("Fail to get bufferHandle");
130 return AVCS_ERR_UNKNOWN;
131 }
132 stride_ = bufferHandle->stride;
133 return stride_;
134 }
135
GetFence()136 int32_t SurfaceMemory::GetFence()
137 {
138 return fence_;
139 }
140
ClearUsedSize()141 void SurfaceMemory::ClearUsedSize()
142 {
143 size_ = 0;
144 }
145
SetNeedRender(bool needRender)146 void SurfaceMemory::SetNeedRender(bool needRender)
147 {
148 needRender_ = needRender;
149 }
150
UpdateSurfaceBufferScaleMode()151 void SurfaceMemory::UpdateSurfaceBufferScaleMode()
152 {
153 if (surfaceBuffer_ == nullptr) {
154 AVCODEC_LOGE("surfaceBuffer is nullptr");
155 return;
156 }
157 auto ret = surface_->SetScalingMode(surfaceBuffer_->GetSeqNum(), scalingMode_);
158 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
159 AVCODEC_LOGE("update surface buffer scaling mode fail, ret: %{public}" PRIu64, static_cast<uint64_t>(ret));
160 }
161 }
162
SetSurface(sptr<Surface> surface)163 void SurfaceMemory::SetSurface(sptr<Surface> surface)
164 {
165 surface_ = surface;
166 }
167
SetConfig(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t strideAlign,int32_t timeout)168 void SurfaceMemory::SetConfig(int32_t width, int32_t height, int32_t format, uint64_t usage, int32_t strideAlign,
169 int32_t timeout)
170 {
171 requestConfig_ = {.width = width,
172 .height = height,
173 .strideAlignment = strideAlign,
174 .format = format,
175 .usage = usage,
176 .timeout = timeout};
177 }
178
SetScaleType(ScalingMode videoScaleMode)179 void SurfaceMemory::SetScaleType(ScalingMode videoScaleMode)
180 {
181 scalingMode_ = videoScaleMode;
182 }
183
GetBase() const184 uint8_t *SurfaceMemory::GetBase() const
185 {
186 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, nullptr, "surfaceBuffer is nullptr");
187 return static_cast<uint8_t *>(surfaceBuffer_->GetVirAddr());
188 }
189
GetUsedSize() const190 int32_t SurfaceMemory::GetUsedSize() const
191 {
192 return size_;
193 }
194
GetSize() const195 int32_t SurfaceMemory::GetSize() const
196 {
197 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, -1, "surfaceBuffer is nullptr");
198 uint32_t size = surfaceBuffer_->GetSize();
199 return static_cast<int32_t>(size);
200 }
201
GetFlags() const202 uint32_t SurfaceMemory::GetFlags() const
203 {
204 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, 0, "surfaceBuffer is nullptr");
205 return FLAGS_READ_WRITE;
206 }
207 } // namespace MediaAVCodec
208 } // namespace OHOS
209