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