1 /*
2 * Copyright (c) 2021-2021 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 #if !defined(OHOS_LITE) && defined(VIDEO_SUPPORT)
17
18 #define HST_LOG_TAG "SurfaceSinkPlugin"
19
20 #include "surface_sink_plugin.h"
21 #include <functional>
22 #include <algorithm>
23 #include "string_ex.h"
24 #include "param_wrapper.h"
25 #include "surface_buffer_impl.h"
26 #include "securec.h"
27 #include "foundation/log.h"
28 #include "utils/constants.h"
29 #include "plugin/common/surface_memory.h"
30
31 namespace {
32 using namespace OHOS::Media::Plugin;
33 using namespace VidSurfaceSinkPlugin;
34 constexpr uint32_t DEFAULT_WIDTH = 640;
35 constexpr uint32_t DEFAULT_HEIGHT = 480;
36 constexpr uint32_t DEFAULT_BUFFER_NUM = 25;
37 constexpr int32_t DEFAULT_STRIDE_ALIGN = 16;
38
VideoSinkPluginCreator(const std::string & name)39 std::shared_ptr<VideoSinkPlugin> VideoSinkPluginCreator(const std::string& name)
40 {
41 return std::make_shared<SurfaceSinkPlugin>(name);
42 }
43
SurfaceSinkRegister(const std::shared_ptr<Register> & reg)44 Status SurfaceSinkRegister(const std::shared_ptr<Register>& reg)
45 {
46 VideoSinkPluginDef definition;
47 definition.name = "surface_sink";
48 definition.rank = 100; // 100
49 Capability cap(OHOS::Media::MEDIA_MIME_VIDEO_RAW);
50 cap.AppendDiscreteKeys<VideoPixelFormat>(
51 Capability::Key::VIDEO_PIXEL_FORMAT,
52 {VideoPixelFormat::RGBA, VideoPixelFormat::NV12});
53 definition.inCaps.emplace_back(cap);
54 definition.creator = VideoSinkPluginCreator;
55 return reg->AddPlugin(definition);
56 }
57
__anon443fd3030202null58 PLUGIN_DEFINITION(StdVideoSurfaceSink, LicenseType::APACHE_V2, SurfaceSinkRegister, [] {});
59 } // namespace
60
61 namespace OHOS {
62 namespace Media {
63 namespace Plugin {
64 namespace VidSurfaceSinkPlugin {
TranslatePixelFormat(const VideoPixelFormat pixelFormat)65 static PixelFormat TranslatePixelFormat(const VideoPixelFormat pixelFormat)
66 {
67 PixelFormat surfaceFormat = PixelFormat::PIXEL_FMT_BUTT;
68 switch (pixelFormat) {
69 case VideoPixelFormat::YUV420P:
70 surfaceFormat = PixelFormat::PIXEL_FMT_YCBCR_420_P;
71 break;
72 case VideoPixelFormat::YUYV422:
73 surfaceFormat = PixelFormat::PIXEL_FMT_YUYV_422_PKG;
74 break;
75 case VideoPixelFormat::RGBA:
76 surfaceFormat = PixelFormat::PIXEL_FMT_RGBA_8888;
77 break;
78 case VideoPixelFormat::BGRA:
79 surfaceFormat = PixelFormat::PIXEL_FMT_BGRA_8888;
80 break;
81 case VideoPixelFormat::YUV422P:
82 surfaceFormat = PixelFormat::PIXEL_FMT_YUV_422_I;
83 break;
84 case VideoPixelFormat::ARGB:
85 case VideoPixelFormat::ABGR:
86 case VideoPixelFormat::RGB24:
87 case VideoPixelFormat::BGR24:
88 case VideoPixelFormat::YUV444P:
89 case VideoPixelFormat::YUV410P:
90 case VideoPixelFormat::YUV411P:
91 case VideoPixelFormat::GRAY8:
92 case VideoPixelFormat::MONOWHITE:
93 case VideoPixelFormat::MONOBLACK:
94 case VideoPixelFormat::PAL8:
95 case VideoPixelFormat::YUVJ420P:
96 case VideoPixelFormat::YUVJ422P:
97 case VideoPixelFormat::YUVJ444P:
98 break;
99 case VideoPixelFormat::NV12:
100 surfaceFormat = PixelFormat::PIXEL_FMT_YCBCR_420_SP;
101 break;
102 case VideoPixelFormat::NV21:
103 surfaceFormat = PixelFormat::PIXEL_FMT_YCRCB_420_SP;
104 break;
105 default:
106 break;
107 }
108 return surfaceFormat;
109 }
110
SurfaceSinkPlugin(std::string name)111 SurfaceSinkPlugin::SurfaceSinkPlugin(std::string name)
112 : VideoSinkPlugin(std::move(name)),
113 width_(DEFAULT_WIDTH),
114 height_(DEFAULT_HEIGHT),
115 pixelFormat_(VideoPixelFormat::NV21),
116 maxSurfaceNum_(DEFAULT_BUFFER_NUM),
117 needConvFormat(false)
118 {
119 }
120
Init()121 Status SurfaceSinkPlugin::Init()
122 {
123 std::weak_ptr<SurfaceSinkPlugin> weakPtr(shared_from_this());
124 // must get the surface_ from app
125 if (surface_ == nullptr) {
126 OSAL::ScopedLock lock(mutex_);
127 surfaceCond_.Wait(lock, [this] { return surface_ != nullptr; });
128 }
129 #ifdef DUMP_RAW_DATA
130 dumpFd_ = std::fopen("./vsink_out.dat", "wb");
131 #endif
132 MEDIA_LOG_D("get surface success");
133 return Status::OK;
134 }
135
Deinit()136 Status SurfaceSinkPlugin::Deinit()
137 {
138 #ifdef DUMP_RAW_DATA
139 if (dumpFd_) {
140 std::fclose(dumpFd_);
141 dumpFd_ = nullptr;
142 }
143 #endif
144 surface_ = nullptr;
145 return Status::OK;
146 }
147
Prepare()148 Status SurfaceSinkPlugin::Prepare()
149 {
150 FALSE_RETURN_V_MSG_E(surface_ != nullptr && mAllocator_ != nullptr,
151 Status::ERROR_UNKNOWN, "need surface config first");
152 FALSE_RETURN_V_MSG_E(surface_->SetQueueSize(maxSurfaceNum_) == OHOS::SurfaceError::SURFACE_ERROR_OK,
153 Status::ERROR_UNKNOWN, "surface SetQueueSize fail");
154 PixelFormat pluginFmt = TranslatePixelFormat(pixelFormat_);
155 if (pluginFmt == PixelFormat::PIXEL_FMT_BUTT) {
156 MEDIA_LOG_E("surface can not support pixel format: " PUBLIC_LOG_U32, pixelFormat_);
157 return Status::ERROR_UNKNOWN;
158 }
159 const std::string surfaceFmtStr = "SURFACE_FORMAT";
160 std::string formatStr = surface_->GetUserData(surfaceFmtStr);
161 PixelFormat surfaceFmt = PIXEL_FMT_BUTT;
162 if (formatStr == std::to_string(PixelFormat::PIXEL_FMT_RGBA_8888)) {
163 surfaceFmt = PixelFormat::PIXEL_FMT_RGBA_8888;
164 }
165 if (pluginFmt != surfaceFmt) {
166 MEDIA_LOG_W("plugin format: " PUBLIC_LOG_U32 " is diff from surface format: " PUBLIC_LOG_U32,
167 static_cast<uint32_t>(pluginFmt), static_cast<uint32_t>(surfaceFmt));
168 if (pixelFormat_ != VideoPixelFormat::NV12) {
169 // need to convert pixel format when write
170 needConvFormat = true;
171 }
172 }
173 uint64_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
174 if (pixelFormat_ == VideoPixelFormat::NV12) {
175 surfaceFmt = PixelFormat::PIXEL_FMT_YCBCR_420_SP;
176 } else if (pixelFormat_ == VideoPixelFormat::NV21) {
177 surfaceFmt = PixelFormat::PIXEL_FMT_YCRCB_420_SP;
178 }
179 MEDIA_LOG_D("pixelFormat: " PUBLIC_LOG_U32 ", surfaceFmt: " PUBLIC_LOG_U32,
180 static_cast<uint32_t>(pixelFormat_), static_cast<uint32_t>(surfaceFmt));
181 mAllocator_->Config(static_cast<int32_t>(width_), static_cast<int32_t>(height_), usage, surfaceFmt,
182 DEFAULT_STRIDE_ALIGN, 0);
183 MEDIA_LOG_D("Prepare success");
184 return Status::OK;
185 }
186
Reset()187 Status SurfaceSinkPlugin::Reset()
188 {
189 MEDIA_LOG_D("Reset success");
190 #ifdef DUMP_RAW_DATA
191 if (dumpFd_) {
192 std::fclose(dumpFd_);
193 dumpFd_ = nullptr;
194 }
195 #endif
196 return Status::OK;
197 }
198
Start()199 Status SurfaceSinkPlugin::Start()
200 {
201 MEDIA_LOG_D("Start success");
202 return Status::OK;
203 }
204
Stop()205 Status SurfaceSinkPlugin::Stop()
206 {
207 MEDIA_LOG_D("Stop success");
208 if (surface_) {
209 surface_->CleanCache();
210 }
211 return Status::OK;
212 }
213
GetParameter(Tag tag,ValueType & value)214 Status SurfaceSinkPlugin::GetParameter(Tag tag, ValueType& value)
215 {
216 return Status::ERROR_UNIMPLEMENTED;
217 }
218
SetParameter(Tag tag,const ValueType & value)219 Status SurfaceSinkPlugin::SetParameter(Tag tag, const ValueType& value)
220 {
221 OSAL::ScopedLock lock(mutex_);
222 switch (tag) {
223 case Tag::VIDEO_WIDTH: {
224 if (value.SameTypeWith(typeid(uint32_t))) {
225 width_ = Plugin::AnyCast<uint32_t>(value);
226 MEDIA_LOG_D("width_: " PUBLIC_LOG_U32, width_);
227 }
228 break;
229 }
230 case Tag::VIDEO_HEIGHT: {
231 if (value.SameTypeWith(typeid(uint32_t))) {
232 height_ = Plugin::AnyCast<uint32_t>(value);
233 MEDIA_LOG_D("height_: " PUBLIC_LOG_U32, height_);
234 }
235 break;
236 }
237 case Tag::VIDEO_PIXEL_FORMAT: {
238 if (value.SameTypeWith(typeid(VideoPixelFormat))) {
239 pixelFormat_ = Plugin::AnyCast<VideoPixelFormat>(value);
240 MEDIA_LOG_D("pixelFormat: " PUBLIC_LOG_U32, static_cast<uint32_t>(pixelFormat_));
241 }
242 break;
243 }
244 case Tag::VIDEO_SURFACE: {
245 if (value.SameTypeWith(typeid(sptr<Surface>))) {
246 surface_ = Plugin::AnyCast<sptr<Surface>>(value);
247 if (!surface_) {
248 MEDIA_LOG_E("surface is null");
249 return Status::ERROR_INVALID_PARAMETER;
250 }
251 mAllocator_ = std::make_shared<SurfaceAllocator>(surface_);
252 surfaceCond_.NotifyAll();
253 }
254 break;
255 }
256 case Tag::VIDEO_MAX_SURFACE_NUM: {
257 if (value.SameTypeWith(typeid(uint32_t))) {
258 auto bufferNum = Plugin::AnyCast<uint32_t>(value);
259 if (bufferNum < DEFAULT_BUFFER_NUM) {
260 maxSurfaceNum_ = bufferNum;
261 }
262 MEDIA_LOG_D("maxSurfaceNum_: " PUBLIC_LOG_U32, maxSurfaceNum_);
263 }
264 break;
265 }
266 default:
267 MEDIA_LOG_I("Unknown key");
268 break;
269 }
270 return Status::OK;
271 }
272
GetAllocator()273 std::shared_ptr<Allocator> SurfaceSinkPlugin::GetAllocator()
274 {
275 return mAllocator_;
276 }
277
SetCallback(Callback * cb)278 Status SurfaceSinkPlugin::SetCallback(Callback* cb)
279 {
280 return Status::ERROR_UNIMPLEMENTED;
281 }
282
Pause()283 Status SurfaceSinkPlugin::Pause()
284 {
285 return Status::OK;
286 }
287
Resume()288 Status SurfaceSinkPlugin::Resume()
289 {
290 return Status::OK;
291 }
292
UpdateSurfaceBuffer(sptr<SurfaceBuffer> surfaceBuffer,int32_t fence)293 Status SurfaceSinkPlugin::UpdateSurfaceBuffer(sptr<SurfaceBuffer> surfaceBuffer, int32_t fence)
294 {
295 FALSE_RETURN_V_MSG_E(surfaceBuffer != nullptr, Status::ERROR_NULL_POINTER, "surfaceBuffer is NULL");
296 #ifdef DUMP_RAW_DATA
297 if (dumpFd_ && surfaceBuffer->GetVirAddr()) {
298 std::fwrite(reinterpret_cast<const char*>(surfaceBuffer->GetVirAddr()),
299 surfaceBuffer->GetSize(), 1, dumpFd_);
300 }
301 #endif
302 FALSE_RETURN_V_MSG_E(needConvFormat == false, Status::ERROR_UNIMPLEMENTED, "Need to convert format");
303 OHOS::BufferFlushConfig flushConfig = {
304 {0, 0, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight()},
305 };
306 auto res = surface_->FlushBuffer(surfaceBuffer, fence, flushConfig);
307 if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) {
308 MEDIA_LOG_W("surface FlushBuffer fail: " PUBLIC_LOG_D32, res);
309 res = surface_->CancelBuffer(surfaceBuffer);
310 FALSE_RETURN_V_MSG_W(res == OHOS::SurfaceError::SURFACE_ERROR_OK, Status::ERROR_UNKNOWN,
311 "surface CancelBuffer fail: " PUBLIC_LOG_D32, res);
312 }
313 return Status::OK;
314 }
315
Write(const std::shared_ptr<Buffer> & inputInfo)316 Status SurfaceSinkPlugin::Write(const std::shared_ptr<Buffer>& inputInfo)
317 {
318 MEDIA_LOG_D("SurfaceSink write begin");
319 if (inputInfo == nullptr || inputInfo->IsEmpty()) {
320 return Status::ERROR_INVALID_PARAMETER;
321 }
322 auto memory = inputInfo->GetMemory();
323 FALSE_RETURN_V_MSG_E(memory != nullptr, Status::ERROR_NULL_POINTER, "GetMemory fail");
324 FALSE_RETURN_V_MSG_E(memory->GetMemoryType() == MemoryType::SURFACE_BUFFER, Status::ERROR_INVALID_PARAMETER,
325 "memory type is not SURFACE_BUFFER");
326 std::shared_ptr<SurfaceMemory> surfaceMemory = ReinterpretPointerCast<SurfaceMemory>(memory);
327 auto ret = UpdateSurfaceBuffer(surfaceMemory->GetSurfaceBuffer(), surfaceMemory->GetFlushFence());
328 if (ret != Status::OK) {
329 MEDIA_LOG_W("UpdateSurfaceBuffer fail: " PUBLIC_LOG_U32, ret);
330 }
331 // After surface buffer sending to surface, we need to clear sptr.
332 // So that we can request again surface buffer on the same SurfaceMemory
333 surfaceMemory->ReleaseSurfaceBuffer();
334 MEDIA_LOG_D("SurfaceSink write success");
335 return Status::OK;
336 }
337
Flush()338 Status SurfaceSinkPlugin::Flush()
339 {
340 return Status::OK;
341 }
342
GetLatency(uint64_t & nanoSec)343 Status SurfaceSinkPlugin::GetLatency(uint64_t& nanoSec)
344 {
345 nanoSec = 10; // 10 ns
346 return Status::OK;
347 }
348 } // namespace VidSurfaceSinkPlugin
349 } // namespace Plugin
350 } // namespace Media
351 } // namespace OHOS
352
353 #endif