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