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