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 "fsurface_memory.h"
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AvCodec-FSurfaceMemory"};
23 }
24 namespace OHOS {
25 namespace MediaAVCodec {
26 sptr<Surface> FSurfaceMemory::surface_ = nullptr;
27 BufferRequestConfig FSurfaceMemory::requestConfig_ = {0};
28 ScalingMode FSurfaceMemory::scalingMode_ = {ScalingMode::SCALING_MODE_SCALE_TO_WINDOW};
29
30
Create()31 std::shared_ptr<FSurfaceMemory> FSurfaceMemory::Create()
32 {
33 CHECK_AND_RETURN_RET_LOG(surface_ != nullptr, nullptr, "surface is nullptr");
34 CHECK_AND_RETURN_RET_LOG(requestConfig_.width != 0 && requestConfig_.height != 0, nullptr,
35 "surface config invalid");
36 std::shared_ptr<FSurfaceMemory> buffer = std::make_shared<FSurfaceMemory>();
37 buffer->AllocSurfaceBuffer();
38 return buffer;
39 }
40
~FSurfaceMemory()41 FSurfaceMemory::~FSurfaceMemory()
42 {
43 ReleaseSurfaceBuffer();
44 }
45
AllocSurfaceBuffer()46 void FSurfaceMemory::AllocSurfaceBuffer()
47 {
48 if (surface_ == nullptr || surfaceBuffer_ != nullptr) {
49 AVCODEC_LOGE("surface is nullptr or surfaceBuffer is not nullptr");
50 return;
51 }
52 fence_ = -1;
53 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
54 auto ret = surface_->RequestBuffer(surfaceBuffer, fence_, requestConfig_);
55 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK || surfaceBuffer == nullptr) {
56 if (ret == OHOS::SurfaceError::SURFACE_ERROR_NO_BUFFER) {
57 AVCODEC_LOGD("buffer queue is no more buffers");
58 } else {
59 AVCODEC_LOGE("surface RequestBuffer fail, ret: %{public}" PRIu64, static_cast<uint64_t>(ret));
60 }
61 return;
62 }
63
64 surfaceBuffer_ = surfaceBuffer;
65 AVCODEC_LOGD("request surface buffer success, releaseFence: %{public}d", fence_);
66 }
67
ReleaseSurfaceBuffer()68 void FSurfaceMemory::ReleaseSurfaceBuffer()
69 {
70 if (surfaceBuffer_ == nullptr) {
71 return;
72 }
73 if (!needRender_) {
74 auto ret = surface_->CancelBuffer(surfaceBuffer_);
75 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
76 AVCODEC_LOGE("surface CancelBuffer fail, ret: %{public}" PRIu64, static_cast<uint64_t>(ret));
77 }
78 }
79 surfaceBuffer_ = nullptr;
80 }
81
GetSurfaceBuffer()82 sptr<SurfaceBuffer> FSurfaceMemory::GetSurfaceBuffer()
83 {
84 if (!surfaceBuffer_) {
85 // request surface buffer again when old buffer flush to nullptr
86 AllocSurfaceBuffer();
87 }
88 return surfaceBuffer_;
89 }
90
GetSurfaceBufferStride()91 int32_t FSurfaceMemory::GetSurfaceBufferStride()
92 {
93 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, 0, "surfaceBuffer is nullptr");
94 auto bufferHandle = surfaceBuffer_->GetBufferHandle();
95 if (bufferHandle == nullptr) {
96 AVCODEC_LOGE("Fail to get bufferHandle");
97 return AVCS_ERR_UNKNOWN;
98 }
99 stride_ = bufferHandle->stride;
100 return stride_;
101 }
102
GetFence()103 int32_t FSurfaceMemory::GetFence()
104 {
105 return fence_;
106 }
107
SetNeedRender(bool needRender)108 void FSurfaceMemory::SetNeedRender(bool needRender)
109 {
110 needRender_ = needRender;
111 }
112
UpdateSurfaceBufferScaleMode()113 void FSurfaceMemory::UpdateSurfaceBufferScaleMode()
114 {
115 if (surfaceBuffer_ == nullptr) {
116 AVCODEC_LOGE("surfaceBuffer is nullptr");
117 return;
118 }
119 auto ret = surface_->SetScalingMode(surfaceBuffer_->GetSeqNum(), scalingMode_);
120 if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
121 AVCODEC_LOGE("update surface buffer scaling mode fail, ret: %{public}" PRIu64, static_cast<uint64_t>(ret));
122 }
123 }
124
SetSurface(sptr<Surface> surface)125 void FSurfaceMemory::SetSurface(sptr<Surface> surface)
126 {
127 surface_ = surface;
128 }
129
SetConfig(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t strideAlign,int32_t timeout)130 void FSurfaceMemory::SetConfig(int32_t width, int32_t height, int32_t format, uint64_t usage, int32_t strideAlign,
131 int32_t timeout)
132 {
133 requestConfig_ = {.width = width,
134 .height = height,
135 .strideAlignment = strideAlign,
136 .format = format,
137 .usage = usage,
138 .timeout = timeout};
139 }
140
SetScaleType(ScalingMode videoScaleMode)141 void FSurfaceMemory::SetScaleType(ScalingMode videoScaleMode)
142 {
143 scalingMode_ = videoScaleMode;
144 }
145
GetBase() const146 uint8_t *FSurfaceMemory::GetBase() const
147 {
148 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, nullptr, "surfaceBuffer is nullptr");
149 return static_cast<uint8_t *>(surfaceBuffer_->GetVirAddr());
150 }
151
GetSize() const152 int32_t FSurfaceMemory::GetSize() const
153 {
154 CHECK_AND_RETURN_RET_LOG(surfaceBuffer_ != nullptr, -1, "surfaceBuffer is nullptr");
155 uint32_t size = surfaceBuffer_->GetSize();
156 return static_cast<int32_t>(size);
157 }
158 } // namespace MediaAVCodec
159 } // namespace OHOS
160