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