• 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 <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