• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 #include "2.0/include/screenregion.h"
17 
18 #include <securec.h>
19 #include "display_manager.h"
20 #include "dscreen_constants.h"
21 #include "dscreen_errcode.h"
22 #include "dscreen_fwkkit.h"
23 #include "dscreen_hisysevent.h"
24 #include "dscreen_log.h"
25 #include "dscreen_json_util.h"
26 #include "dscreen_util.h"
27 #include "screen.h"
28 #include "screen_client.h"
29 #include "screen_client_common.h"
30 
31 namespace OHOS {
32 namespace DistributedHardware {
33 namespace V2_0 {
ScreenRegion(const std::string & remoteDevId)34 ScreenRegion::ScreenRegion(const std::string &remoteDevId) : screenId_(0), displayId_(0), remoteDevId_(remoteDevId)
35 {
36     DHLOGI("ScreenRegion ctor.");
37     frameNumber_.store(0);
38 }
39 
~ScreenRegion()40 ScreenRegion::~ScreenRegion()
41 {
42     DHLOGI("ScreenRegion dctor.");
43     if (receiverAdapter_ != nullptr) {
44         receiverAdapter_->Release();
45     }
46     receiverAdapter_ = nullptr;
47     frameNumber_.store(0);
48 }
49 
InitReceiverEngine(IAVEngineProvider * providerPtr)50 int32_t ScreenRegion::InitReceiverEngine(IAVEngineProvider *providerPtr)
51 {
52     DHLOGI("InitReceiverEngine enter.");
53     if (receiverAdapter_ == nullptr) {
54         receiverAdapter_ = std::make_shared<AVTransReceiverAdapter>();
55     }
56     int32_t ret = receiverAdapter_->Initialize(providerPtr, remoteDevId_);
57     if (ret != DH_SUCCESS) {
58         DHLOGE("initialize av receiver adapter failed.");
59         return ERR_DH_AV_TRANS_INIT_FAILED;
60     }
61     return receiverAdapter_->RegisterAdapterCallback(shared_from_this());
62 }
63 
Release()64 int32_t ScreenRegion::Release()
65 {
66     DHLOGI("ScreenRegion::Release remoteDevId: %s", GetAnonyString(remoteDevId_).c_str());
67     if (!isRunning) {
68         DHLOGI("ScreenRegion not running, no need release");
69         return DH_SUCCESS;
70     }
71     ScreenClient::GetInstance().RemoveWindow(windowId_);
72 
73     if (receiverAdapter_ == nullptr) {
74         DHLOGE("av transport receiver adapter is nullptr.");
75         return ERR_DH_AV_TRANS_NULL_VALUE;
76     }
77 
78     int32_t ret = receiverAdapter_->Stop();
79     if (ret != DH_SUCCESS) {
80         DHLOGE("sink trans stop failed.");
81     }
82 
83     ret = receiverAdapter_->Release();
84     if (ret != DH_SUCCESS) {
85         DHLOGE("release av receiver adapter failed.");
86     }
87 
88     isRunning = false;
89     return DH_SUCCESS;
90 }
91 
StartReceiverEngine(const std::string & content)92 int32_t ScreenRegion::StartReceiverEngine(const std::string &content)
93 {
94     DHLOGI("StartReceiverEngine enter.");
95     if (receiverAdapter_ == nullptr) {
96         DHLOGE("av transport receiver adapter is null.");
97         return ERR_DH_AV_TRANS_NULL_VALUE;
98     }
99     int32_t ret = SetUp(content);
100     if (ret != DH_SUCCESS) {
101         DHLOGE("set up av receiver parameter failed.");
102         return ERR_DH_AV_TRANS_SETUP_FAILED;
103     }
104     ret = receiverAdapter_->Start();
105     if (ret != DH_SUCCESS) {
106         DHLOGE("start av receiver engine failed.");
107         return ERR_DH_AV_TRANS_START_FAILED;
108     }
109     isRunning = true;
110     PublishMessage(DHTopic::TOPIC_SINK_PROJECT_WINDOW_INFO, screenId_, remoteDevId_, windowId_, windowProperty_);
111     return DH_SUCCESS;
112 }
113 
StopReceiverEngine()114 int32_t ScreenRegion::StopReceiverEngine()
115 {
116     DHLOGI("StopReceiverEngine, remoteDevId: %s, screenId is: %" PRIu64,
117         GetAnonyString(remoteDevId_).c_str(), screenId_);
118 
119     int32_t ret = ScreenClient::GetInstance().RemoveWindow(windowId_);
120     if (ret != DH_SUCCESS) {
121         DHLOGE("remove window failed.");
122     }
123 
124     if (receiverAdapter_ == nullptr) {
125         DHLOGE("av transport receiver adapter is null.");
126         return ERR_DH_AV_TRANS_NULL_VALUE;
127     }
128     return receiverAdapter_->Stop();
129 }
130 
SetUp(const std::string & content)131 int32_t ScreenRegion::SetUp(const std::string &content)
132 {
133     json contentJson = json::parse(content, nullptr, false);
134     if (contentJson.is_discarded()) {
135         return ERR_DH_SCREEN_INPUT_PARAM_INVALID;
136     }
137     if (!CheckContentJson(contentJson) || !contentJson.contains(KEY_VIDEO_PARAM) ||
138         !contentJson.contains(KEY_MAPRELATION)) {
139         return ERR_DH_SCREEN_INPUT_PARAM_INVALID;
140     }
141     screenId_ = contentJson[KEY_SCREEN_ID].get<uint64_t>();
142     displayId_ = Rosen::DisplayManager::GetInstance().GetDefaultDisplayId();
143     videoParam_ = std::make_shared<VideoParam>(contentJson[KEY_VIDEO_PARAM].get<VideoParam>());
144     mapRelation_ = std::make_shared<DScreenMapRelation>(contentJson[KEY_MAPRELATION].get<DScreenMapRelation>());
145 
146     int32_t ret = ConfigWindow();
147     if (ret != DH_SUCCESS) {
148         DHLOGE("config dscreen region window failed.");
149         return ret;
150     }
151     std::string codecType;
152     if (videoParam_->GetCodecType() == VIDEO_CODEC_TYPE_VIDEO_H265) {
153         codecType = MIME_VIDEO_H265;
154     } else if (videoParam_->GetCodecType() == VIDEO_CODEC_TYPE_VIDEO_H264) {
155         codecType = MIME_VIDEO_H264;
156     } else {
157         codecType = MIME_VIDEO_RAW;
158     }
159     std::string pixelFormat;
160     if (videoParam_->GetVideoFormat() == VIDEO_DATA_FORMAT_YUVI420) {
161         pixelFormat = VIDEO_FORMAT_YUVI420;
162     } else if (videoParam_->GetVideoFormat() == VIDEO_DATA_FORMAT_NV12) {
163         pixelFormat = VIDEO_FORMAT_NV12;
164     } else if (videoParam_->GetVideoFormat() == VIDEO_DATA_FORMAT_NV21) {
165         pixelFormat = VIDEO_FORMAT_NV21;
166     } else {
167         pixelFormat = VIDEO_FORMAT_RGBA8888;
168     }
169     receiverAdapter_->SetParameter(AVTransTag::VIDEO_CODEC_TYPE, codecType);
170     receiverAdapter_->SetParameter(AVTransTag::VIDEO_PIXEL_FORMAT, pixelFormat);
171     receiverAdapter_->SetParameter(AVTransTag::VIDEO_WIDTH, std::to_string(videoParam_->GetVideoWidth()));
172     receiverAdapter_->SetParameter(AVTransTag::VIDEO_HEIGHT, std::to_string(videoParam_->GetVideoHeight()));
173     receiverAdapter_->SetParameter(AVTransTag::VIDEO_FRAME_RATE, std::to_string(videoParam_->GetFps()));
174     receiverAdapter_->SetParameter(AVTransTag::ENGINE_READY, OWNER_NAME_D_SCREEN);
175 
176     alignedHeight_ = videoParam_->GetVideoHeight();
177     if (alignedHeight_ % ALIGNEDBITS != 0) {
178         alignedHeight_ = ((alignedHeight_ / ALIGNEDBITS) +1) * ALIGNEDBITS;
179     }
180     return DH_SUCCESS;
181 }
182 
ConfigWindow()183 int32_t ScreenRegion::ConfigWindow()
184 {
185     DHLOGI("ConfigWindow enter");
186     std::shared_ptr<WindowProperty> windowProperty = std::make_shared<WindowProperty>();
187     windowProperty->displayId = displayId_;
188     if (mapRelation_ == nullptr) {
189         DHLOGE("mapRelation is nullptr.");
190         return ERR_DH_SCREEN_SA_DSCREEN_SCREENGION_SETUP_FAILED;
191     }
192     ScreenRect screenRect = mapRelation_->GetScreenRect();
193     windowProperty->startX = screenRect.startX;
194     windowProperty->startY = screenRect.startY;
195     windowProperty->width = screenRect.width;
196     windowProperty->height = screenRect.height;
197     windowProperty_ = windowProperty;
198 
199     windowId_ = ScreenClient::GetInstance().AddWindow(windowProperty);
200     if (windowId_ < 0) {
201         DHLOGE("AddWindow failed.");
202         ReportOptFail(DSCREEN_OPT_FAIL, ERR_DH_SCREEN_SA_DSCREEN_SCREENGION_SETUP_FAILED, "AddWindow failed.");
203         return ERR_DH_SCREEN_SA_DSCREEN_SCREENGION_SETUP_FAILED;
204     }
205     int32_t ret = ScreenClient::GetInstance().ShowWindow(windowId_);
206     if (ret != DH_SUCCESS) {
207         DHLOGE("show window failed.");
208         ReportOptFail(DSCREEN_OPT_FAIL, ret, "show window failed.");
209         return ERR_DH_SCREEN_SA_DSCREEN_SCREENGION_SETUP_FAILED;
210     }
211 
212     sptr<Surface> surface = ScreenClient::GetInstance().GetSurface(windowId_);
213     if (surface == nullptr) {
214         DHLOGE("get window surface failed.");
215         ReportOptFail(DSCREEN_OPT_FAIL, ERR_DH_SCREEN_SA_DSCREEN_SCREENGION_SETUP_FAILED, "get window surface failed.");
216         return ERR_DH_SCREEN_SA_DSCREEN_SCREENGION_SETUP_FAILED;
217     }
218     windowSurface_ = surface;
219     return DH_SUCCESS;
220 }
221 
PublishMessage(const DHTopic topic,const uint64_t & screenId,const std::string & remoteDevId,const int32_t & windowId,std::shared_ptr<WindowProperty> windowProperty)222 void ScreenRegion::PublishMessage(const DHTopic topic, const uint64_t &screenId,
223     const std::string &remoteDevId, const int32_t &windowId, std::shared_ptr<WindowProperty> windowProperty)
224 {
225     DHLOGI("ScreenRegion PublishMessage");
226     if (DScreenFwkKit::GetInstance().GetDHFwkKit() == nullptr) {
227         DHLOGE("GetDHFwkKit fail.");
228         return;
229     }
230     json messageJosn;
231     std::string message;
232     messageJosn[SOURCE_WIN_ID] = screenId;
233     messageJosn[SOURCE_DEV_ID] = remoteDevId;
234     messageJosn[SINK_SHOW_WIN_ID] = windowId;
235     messageJosn[SINK_PROJ_SHOW_WIDTH] = windowProperty->width;
236     messageJosn[SINK_PROJ_SHOW_HEIGHT] = windowProperty->height;
237     messageJosn[SINK_WIN_SHOW_X] = windowProperty->startX;
238     messageJosn[SINK_WIN_SHOW_Y] = windowProperty->startY;
239     message = messageJosn.dump();
240     DScreenFwkKit::GetInstance().GetDHFwkKit()->PublishMessage(topic, message);
241 }
242 
OnEngineEvent(DScreenEventType event,const std::string & content)243 void ScreenRegion::OnEngineEvent(DScreenEventType event, const std::string &content)
244 {
245     (void)content;
246     if (event == DScreenEventType::ENGINE_ERROR) {
247         StopReceiverEngine();
248     }
249 }
250 
OnEngineMessage(const std::shared_ptr<AVTransMessage> & message)251 void ScreenRegion::OnEngineMessage(const std::shared_ptr<AVTransMessage> &message)
252 {
253     if (message == nullptr) {
254         DHLOGE("received engine message is null.");
255         return;
256     }
257 
258     DHLOGI("On source device engine message received, message type =%d.", message->type_);
259     if (message->type_ == DScreenMsgType::START_MIRROR) {
260         int32_t ret = StartReceiverEngine(message->content_);
261         DScreenMsgType msgType = (ret == DH_SUCCESS) ? DScreenMsgType::START_MIRROR_SUCCESS :
262             DScreenMsgType::START_MIRROR_FAIL;
263 
264         json paramJson;
265         paramJson[KEY_DEV_ID] = remoteDevId_;
266         auto avMessage = std::make_shared<AVTransMessage>(msgType, paramJson.dump(), remoteDevId_);
267         receiverAdapter_->SendMessageToRemote(avMessage);
268     } else if (message->type_ == DScreenMsgType::STOP_MIRROR) {
269         StopReceiverEngine();
270     }
271 }
272 
GetWSBuffer(sptr<OHOS::SurfaceBuffer> & wsBuffer,const std::shared_ptr<AVTransBuffer> & buffer)273 void ScreenRegion::GetWSBuffer(sptr<OHOS::SurfaceBuffer> &wsBuffer, const std::shared_ptr<AVTransBuffer> &buffer)
274 {
275     auto bufferData = buffer->GetBufferData(0);
276     auto bufferAddr = bufferData->GetAddress();
277     auto wsBufAddr = static_cast<uint8_t*>(wsBuffer->GetVirAddr());
278     uint32_t wsBufSize = wsBuffer->GetSize();
279     uint32_t srcOffset = 0;
280     uint32_t dstOffset = 0;
281     uint32_t alignedWidth = videoParam_->GetVideoWidth();
282     uint32_t chromaOffset = videoParam_->GetVideoWidth() * videoParam_->GetVideoHeight();
283 
284     for (unsigned int yh = 0 ; yh < videoParam_->GetVideoHeight(); yh++) {
285         int32_t ret = memcpy_s(wsBufAddr + dstOffset, chromaOffset - dstOffset,
286             bufferAddr + srcOffset, videoParam_->GetVideoWidth());
287         if (ret != EOK) {
288             DHLOGE("memcpy video buffer y data failed,ret: %d.", ret);
289             windowSurface_->CancelBuffer(wsBuffer);
290             return;
291         }
292         dstOffset += videoParam_->GetVideoWidth();
293         srcOffset += alignedWidth;
294     }
295 
296     dstOffset = chromaOffset;
297     srcOffset = alignedWidth * alignedHeight_;
298 
299     for (unsigned int uvh = 0 ; uvh < videoParam_->GetVideoHeight() / TWO; uvh++) {
300         int32_t ret = memcpy_s(wsBufAddr + dstOffset, wsBufSize - dstOffset,
301             bufferAddr + srcOffset, videoParam_->GetVideoWidth());
302         if (ret != EOK) {
303             DHLOGE("memcpy video buffer uv data failed,ret: %d.", ret);
304             windowSurface_->CancelBuffer(wsBuffer);
305             return;
306         }
307         dstOffset += videoParam_->GetVideoWidth();
308         srcOffset += alignedWidth;
309     }
310 }
311 
OnEngineDataDone(const std::shared_ptr<AVTransBuffer> & buffer)312 void ScreenRegion::OnEngineDataDone(const std::shared_ptr<AVTransBuffer> &buffer)
313 {
314     ++frameNumber_;
315     DHLOGI("OnEngineDataDone enter");
316     if (buffer == nullptr) {
317         DHLOGE("received video buffer data is nullptr.");
318         return;
319     }
320     if (windowSurface_ == nullptr) {
321         DHLOGE("window surface is nullptr.");
322         return;
323     }
324     sptr<OHOS::SurfaceBuffer> wsBuffer = nullptr;
325     int32_t releaseFence = -1;
326     OHOS::BufferRequestConfig requestConfig = {
327         .width = videoParam_->GetVideoWidth(),
328         .height = videoParam_->GetVideoHeight(),
329         .strideAlignment = STRIDE_ALIGNMENT,
330         .format = GRAPHIC_PIXEL_FMT_YCRCB_420_SP,
331         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
332     };
333     SurfaceError surfaceErr = windowSurface_->RequestBuffer(wsBuffer, releaseFence, requestConfig);
334     if (surfaceErr != SURFACE_ERROR_OK || wsBuffer == nullptr) {
335         DHLOGE("surface request buffer failed, surfaceErr: %d.", surfaceErr);
336         windowSurface_->CancelBuffer(wsBuffer);
337         return;
338     }
339     GetWSBuffer(wsBuffer, buffer);
340     BufferFlushConfig flushConfig = { {0, 0, wsBuffer->GetWidth(), wsBuffer->GetHeight()}, 0};
341     surfaceErr = windowSurface_->FlushBuffer(wsBuffer, -1, flushConfig);
342     if (surfaceErr != SURFACE_ERROR_OK) {
343         DHLOGE("surface flush buffer failed, surfaceErr: %d.", surfaceErr);
344         windowSurface_->CancelBuffer(wsBuffer);
345         return;
346     }
347     DHLOGI("Fill video buffer data to window surface success. frameNumber: %zu", frameNumber_.load());
348 }
349 
GetScreenId()350 uint64_t ScreenRegion::GetScreenId()
351 {
352     return screenId_;
353 }
354 
GetRemoteDevId()355 std::string ScreenRegion::GetRemoteDevId()
356 {
357     return remoteDevId_;
358 }
359 
GetVideoParam()360 std::shared_ptr<VideoParam> ScreenRegion::GetVideoParam()
361 {
362     return videoParam_;
363 }
364 
GetWindowId()365 int32_t ScreenRegion::GetWindowId()
366 {
367     return windowId_;
368 }
369 
GetWindowProperty()370 std::shared_ptr<WindowProperty> ScreenRegion::GetWindowProperty()
371 {
372     return windowProperty_;
373 }
374 
CheckContentJson(json & contentJson)375 bool ScreenRegion::CheckContentJson(json &contentJson)
376 {
377     if (!IsUInt64(contentJson, KEY_SCREEN_ID)) {
378         return false;
379     }
380     return true;
381 }
382 } // namespace V1_0
383 } // namespace DistributedHardware
384 } // namespace OHOS