• 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 "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