• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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