1 /*
2 * Copyright (c) 2022-2024 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/dscreen.h"
17
18 #include "avcodec_info.h"
19 #include "avcodec_list.h"
20 #include "2.0/include/av_sender_engine_adapter.h"
21 #include "distributed_hardware_fwk_kit.h"
22 #include "histreamer_query_tool.h"
23
24 #include "dscreen_constants.h"
25 #include "dscreen_errcode.h"
26 #include "dscreen_fwkkit.h"
27 #include "dscreen_hisysevent.h"
28 #include "dscreen_json_util.h"
29 #include "dscreen_log.h"
30 #include "dscreen_hidumper.h"
31 #include "dscreen_util.h"
32 #include "xcollie/watchdog.h"
33 #include "common/include/screen_manager_adapter.h"
34 #include "cJSON.h"
35
36 namespace OHOS {
37 namespace DistributedHardware {
38 namespace V2_0 {
39 /* <<ecoder, decoder>, codec> */
40 static const std::map<std::pair<std::string, std::string>, std::string> CODECS_MAP = {
41 {{"HdiCodecAdapter.OMX.rk.video_encoder.hevc", "HdiCodecAdapter.OMX.rk.video_decoder.hevc"}, CODEC_NAME_H265},
42 {{"HdiCodecAdapter.OMX.hisi.video.encoder.hevc", "HdiCodecAdapter.OMX.hisi.video.decoder.hevc"}, CODEC_NAME_H265},
43 {{"HdiCodecAdapter.OMX.rk.video_encoder.avc", "HdiCodecAdapter.OMX.rk.video_decoder.avc"}, CODEC_NAME_H264},
44 {{"HdiCodecAdapter.OMX.hisi.video.encoder.avc", "HdiCodecAdapter.OMX.hisi.video.decoder.avc"}, CODEC_NAME_H264},
45 };
46
DScreen(const std::string & devId,const std::string & dhId,std::shared_ptr<IDScreenCallback> dscreenCallback)47 DScreen::DScreen(const std::string &devId, const std::string &dhId,
48 std::shared_ptr<IDScreenCallback> dscreenCallback)
49 {
50 DHLOGD("DScreen construct, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId).c_str(),
51 GetAnonyString(dhId).c_str());
52 devId_ = devId;
53 dhId_ = dhId;
54 dscreenCallback_ = dscreenCallback;
55 SetState(DISABLED);
56 taskThreadRunning_ = true;
57 watchdogFlag_ = false;
58 taskQueueThread_ = std::thread([this] { this->TaskThreadLoop(); });
59 auto taskFunc = [this]() {
60 if (watchdogFlag_) {
61 watchdogFlag_ = false;
62 } else {
63 DHLOGE("Watchdog : Dscreen TaskThreadLoop dead.");
64 _Exit(0);
65 }
66 };
67 OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask("dscreenwatchdog", taskFunc, WATCHDOG_INTERVAL_TIME_MS,
68 WATCHDOG_DELAY_TIME_MS);
69 }
70
~DScreen()71 DScreen::~DScreen()
72 {
73 DHLOGD("DScreen deconstruct, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
74 GetAnonyString(dhId_).c_str());
75 taskThreadRunning_ = false;
76 taskQueueCond_.notify_all();
77 if (taskQueueThread_.joinable()) {
78 taskQueueThread_.join();
79 }
80 StopSenderEngine();
81 ScreenMgrAdapter::GetInstance().RemoveVirtualScreen(screenId_);
82 videoParam_ = nullptr;
83 senderAdapter_ = nullptr;
84 sinkStartSuccess_ = false;
85 DHLOGD("DScreen deconstruct end.");
86 }
87
AddTask(const std::shared_ptr<Task> & task)88 int32_t DScreen::AddTask(const std::shared_ptr<Task> &task)
89 {
90 DHLOGI("DScreen::AddTask, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
91 GetAnonyString(dhId_).c_str());
92 if (task == nullptr) {
93 DHLOGE("AddTask, task is invalid.");
94 return ERR_DH_SCREEN_SA_DSCREEN_TASK_NOT_VALID;
95 }
96 DHLOGI("AddTask, task type: %{public}" PRId32, task->GetTaskType());
97 {
98 std::lock_guard<std::mutex> lock(taskQueueMtx_);
99 taskQueue_.push(task);
100 }
101 taskQueueCond_.notify_all();
102 return DH_SUCCESS;
103 }
104
HandleTask(const std::shared_ptr<Task> & task)105 void DScreen::HandleTask(const std::shared_ptr<Task> &task)
106 {
107 int32_t taskType = task->GetTaskType();
108 DHLOGI("HandleTask, devId: %{public}s, dhId: %{public}s, task type: %{public}" PRId32,
109 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), taskType);
110 switch (taskType) {
111 case TaskType::TASK_ENABLE:
112 HandleEnable(task->GetTaskParam(), task->GetTaskId());
113 break;
114 case TaskType::TASK_DISABLE:
115 HandleDisable(task->GetTaskId());
116 break;
117 case TaskType::TASK_CONNECT:
118 HandleConnect();
119 break;
120 case TaskType::TASK_DISCONNECT:
121 HandleDisconnect();
122 break;
123 default:
124 DHLOGD("task type unkown.");
125 }
126 }
127
HandleEnable(const std::string & param,const std::string & taskId)128 void DScreen::HandleEnable(const std::string ¶m, const std::string &taskId)
129 {
130 DHLOGI("HandleEnable, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
131 GetAnonyString(dhId_).c_str());
132 if (dscreenCallback_ == nullptr) {
133 DHLOGE("DScreen::HandleEnable, dscreenCallback_ is nullptr");
134 return;
135 }
136 std::lock_guard<std::mutex> lock(ableMtx_);
137 if ((curState_ == ENABLED) || (curState_ == ENABLING) || (curState_ == CONNECTING) ||
138 (curState_ == CONNECTED)) {
139 dscreenCallback_->OnRegResult(shared_from_this(), taskId, DH_SUCCESS, "dscreen enable success.");
140 return;
141 }
142 SetState(ENABLING);
143 ParseInputScreenParam(param, taskId);
144 if (videoParam_ == nullptr) {
145 DHLOGE("DScreen::HandleEnable, videoParam_ is nullptr");
146 return;
147 }
148 uint64_t screenId = ScreenMgrAdapter::GetInstance().CreateVirtualScreen(devId_, dhId_, videoParam_);
149 if (screenId == SCREEN_ID_INVALID) {
150 DHLOGE("HandleEnable, create virtual screen failed.");
151 dscreenCallback_->OnRegResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_ENABLE_FAILED,
152 "create virtual screen failed.");
153 ReportRegisterFail(DSCREEN_REGISTER_FAIL, ERR_DH_SCREEN_SA_ENABLE_FAILED, GetAnonyString(devId_).c_str(),
154 GetAnonyString(dhId_).c_str(), "create virtual screen failed.");
155 return;
156 }
157
158 screenId_ = screenId;
159 SetState(ENABLED);
160 dscreenCallback_->OnRegResult(shared_from_this(), taskId, DH_SUCCESS, "dscreen enable success.");
161 ReportRegisterScreenEvent(DSCREEN_REGISTER, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
162 "dscreen enable success.");
163 }
164
ParseInputScreenParam(const std::string & param,const std::string & taskId)165 void DScreen::ParseInputScreenParam(const std::string ¶m, const std::string &taskId)
166 {
167 json attrJson = json::parse(param, nullptr, false);
168 if (!CheckJsonData(attrJson)) {
169 DHLOGE("HandleEnable, check json data failed.");
170 dscreenCallback_->OnRegResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_ENABLE_FAILED,
171 "enable param json is invalid.");
172 ReportRegisterFail(DSCREEN_REGISTER_FAIL, ERR_DH_SCREEN_SA_ENABLE_FAILED, GetAnonyString(devId_).c_str(),
173 GetAnonyString(dhId_).c_str(), "check json data failed.");
174 SetState(DISABLED);
175 return;
176 }
177 if (videoParam_ == nullptr) {
178 videoParam_ = std::make_shared<VideoParam>();
179 }
180 int32_t ret = NegotiateCodecType(attrJson[KEY_HISTREAMER_VIDEO_DECODER]);
181 if (ret != DH_SUCCESS) {
182 DHLOGE("HandleEnable, negotiate codec type failed.");
183 dscreenCallback_->OnRegResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_ENABLE_FAILED,
184 "negotiate codec type failed.");
185 ReportRegisterFail(DSCREEN_REGISTER_FAIL, ERR_DH_SCREEN_SA_ENABLE_FAILED, GetAnonyString(devId_).c_str(),
186 GetAnonyString(dhId_).c_str(), "negotiate codec type failed.");
187 return;
188 }
189 videoParam_->SetScreenWidth(attrJson[KEY_SCREEN_WIDTH].get<uint32_t>());
190 videoParam_->SetScreenHeight(attrJson[KEY_SCREEN_HEIGHT].get<uint32_t>());
191 }
192
HandleDisable(const std::string & taskId)193 void DScreen::HandleDisable(const std::string &taskId)
194 {
195 DHLOGI("HandleDisable, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
196 GetAnonyString(dhId_).c_str());
197 if (dscreenCallback_ == nullptr) {
198 DHLOGE("DScreen::HandleDisable, dscreenCallback_ is nullptr");
199 return;
200 }
201 SetState(DISABLING);
202 int32_t ret = ScreenMgrAdapter::GetInstance().RemoveVirtualScreen(screenId_);
203 if (ret != DH_SUCCESS) {
204 DHLOGE("HandleDisable, remove virtual screen failed.");
205 dscreenCallback_->OnUnregResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_DISABLE_FAILED,
206 "remove virtual screen failed.");
207 ReportUnRegisterFail(DSCREEN_UNREGISTER_FAIL, ERR_DH_SCREEN_SA_DISABLE_FAILED, GetAnonyString(devId_).c_str(),
208 GetAnonyString(dhId_).c_str(), "remove virtual screen failed.");
209 return;
210 }
211 SetState(DISABLED);
212 dscreenCallback_->OnUnregResult(shared_from_this(), taskId, DH_SUCCESS, "dscreen disable success.");
213 ReportUnRegisterScreenEvent(DSCREEN_UNREGISTER, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
214 "dscreen disable success.");
215 }
216
HandleConnect()217 void DScreen::HandleConnect()
218 {
219 DHLOGI("HandleConnect, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
220 GetAnonyString(dhId_).c_str());
221 if (GetState() != ENABLED) {
222 DHLOGE("GetState is not ENABLED, HandleConnect failed.");
223 return;
224 }
225 SetState(CONNECTING);
226 int32_t ret = StartSenderEngine();
227 if (ret != DH_SUCCESS) {
228 SetState(ENABLED);
229 ScreenMgrAdapter::GetInstance().RemoveScreenFromGroup(screenId_);
230 DHLOGE("HandleConnect, start av transport sender engine failed.");
231 return;
232 }
233 ret = ConfigSurface();
234 if (ret != DH_SUCCESS) {
235 SetState(ENABLED);
236 ScreenMgrAdapter::GetInstance().RemoveScreenFromGroup(screenId_);
237 DHLOGE("HandleConnect, config image surface failed.");
238 return;
239 }
240 SetState(CONNECTED);
241 ReportScreenMirrorEvent(DSCREEN_PROJECT_START, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
242 "dscreen connect success");
243 }
244
HandleDisconnect()245 void DScreen::HandleDisconnect()
246 {
247 DHLOGD("HandleDisconnect, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
248 GetAnonyString(dhId_).c_str());
249 if (curState_ != CONNECTED) {
250 DHLOGE("dscreen is not connected, cannot disconnect");
251 return;
252 }
253 SetState(DISCONNECTING);
254 int32_t ret = StopSenderEngine();
255 if (ret != DH_SUCCESS) {
256 SetState(CONNECTED);
257 DHLOGE("dScreen Stop failed.");
258 return;
259 }
260 SetState(ENABLED);
261 RemoveSurface();
262 Rosen::RSInterfaces::GetInstance().SetVirtualScreenUsingStatus(false);
263 ReportScreenMirrorEvent(DSCREEN_PROJECT_END, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
264 "dscreen disconnect success");
265 }
266
ConfigSurface()267 int32_t DScreen::ConfigSurface()
268 {
269 DHLOGD("ConfigSurface, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
270 GetAnonyString(dhId_).c_str());
271 consumerSurface_ = Surface::CreateSurfaceAsConsumer();
272 if (consumerSurface_ == nullptr) {
273 DHLOGE("Create consumer surface failed.");
274 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
275 }
276 sptr<IBufferProducer> producer = consumerSurface_->GetProducer();
277 if (producer == nullptr) {
278 DHLOGE("Get preducer surface failed.");
279 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
280 }
281 sptr<OHOS::Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
282 if (producerSurface == nullptr) {
283 DHLOGE("Create preducer surface failed.");
284 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
285 }
286 if (consumerBufferListener_ == nullptr) {
287 consumerBufferListener_ = new ConsumBufferListener(shared_from_this());
288 }
289 consumerSurface_->RegisterConsumerListener(consumerBufferListener_);
290 ScreenMgrAdapter::GetInstance().SetImageSurface(screenId_, producerSurface);
291 DHLOGI("ConfigSurface success.");
292 return DH_SUCCESS;
293 }
294
RemoveSurface()295 int32_t DScreen::RemoveSurface()
296 {
297 if (consumerSurface_ == nullptr) {
298 DHLOGE("consumerSurface_ is nullptr.");
299 return ERR_DH_AV_TRANS_NULL_VALUE;
300 }
301 consumerSurface_->UnregisterConsumerListener();
302
303 consumerSurface_ = nullptr;
304 DHLOGI("RemoveSurface success.");
305 return DH_SUCCESS;
306 }
307
OnBufferAvailable()308 void ConsumBufferListener::OnBufferAvailable()
309 {
310 DHLOGI("OnBufferAvailable enter.");
311 if (dScreen_ == nullptr) {
312 DHLOGE("dScreen is nullptr, cannot consume surface buffer.");
313 return;
314 }
315 if (dScreen_->GetState() != CONNECTED) {
316 DHLOGD("screen is not connected, no need consume surface buffer.");
317 return;
318 }
319 dScreen_->ConsumeSurface();
320 }
321
ConsumeSurface()322 void DScreen::ConsumeSurface()
323 {
324 DHLOGI("ConsumeSurface enter.");
325 if (senderAdapter_ == nullptr) {
326 DHLOGE("av transport sender adapter is null.");
327 return;
328 }
329 if (consumerSurface_ == nullptr) {
330 DHLOGE("consumerSurface_ is nullptr, cannot consume surface buffer.");
331 return;
332 }
333 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
334 syncFence_ = SyncFence::INVALID_FENCE;
335 int64_t timestamp = 0;
336 OHOS::Rect damage = {0, 0, 0, 0};
337 SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, syncFence_, timestamp, damage);
338 if (surfaceErr != SURFACE_ERROR_OK) {
339 DHLOGE("consumerSurface_ acquire buffer failed, errcode: %{public}d", surfaceErr);
340 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
341 return;
342 }
343 int32_t retcode = syncFence_->Wait(SURFACE_SYNC_FENCE_TIMEOUT);
344 if (retcode == -ETIME) {
345 DHLOGE("Sync fence wait timeout, retcode is %{public}" PRId32, retcode);
346 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
347 return;
348 }
349 uint32_t surBufSize = surfaceBuffer->GetSize();
350 auto surBufAddr = static_cast<uint8_t*>(surfaceBuffer->GetVirAddr());
351 uint32_t videoWidth = videoParam_->GetVideoWidth();
352 uint32_t videoHeight = videoParam_->GetVideoHeight();
353 VideoData data = { surBufAddr, surBufSize, videoWidth, videoHeight, timestamp, VIDEO_FORMAT_RGBA8888 };
354 #ifdef DUMP_DSCREEN_FILE
355 if (DscreenHidumper::GetInstance().GetFlagStatus() == true) {
356 DHLOGE("HidumperFlag_ = true, exec SaveFile");
357 DscreenHidumper::GetInstance().SaveFile("Screen_BeforeCoding_width(", data);
358 }
359 #endif
360 int32_t ret = senderAdapter_->PushData(data);
361 if (ret != DH_SUCCESS) {
362 DHLOGE("feed buffer to av transport sender failed.");
363 }
364 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
365 DHLOGI("ConsumeSurface success. timestamp=%{public}" PRId64, timestamp);
366 }
367
InitSenderEngine(IAVEngineProvider * providerPtr,const std::string & peerDevId)368 int32_t DScreen::InitSenderEngine(IAVEngineProvider *providerPtr, const std::string &peerDevId)
369 {
370 DHLOGI("InitSenderEngine enter.");
371 if (senderAdapter_ == nullptr) {
372 senderAdapter_ = std::make_shared<AVTransSenderAdapter>();
373 }
374 int32_t ret = senderAdapter_->Initialize(providerPtr, peerDevId);
375 if (ret != DH_SUCCESS) {
376 DHLOGE("initialize av sender adapter failed.");
377 return ERR_DH_AV_TRANS_INIT_FAILED;
378 }
379 return senderAdapter_->RegisterAdapterCallback(shared_from_this());
380 }
381
StartSenderEngine()382 int32_t DScreen::StartSenderEngine()
383 {
384 DHLOGI("StartSenderEngine, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
385 GetAnonyString(dhId_).c_str());
386 if (senderAdapter_ == nullptr) {
387 DHLOGE("av transport sender adapter is null.");
388 return ERR_DH_AV_TRANS_NULL_VALUE;
389 }
390 int32_t ret = senderAdapter_->CreateControlChannel(devId_);
391 if (ret != DH_SUCCESS) {
392 DHLOGE("create av sender control channel failed.");
393 return ERR_DH_AV_TRANS_CREATE_CHANNEL_FAILED;
394 }
395 ret = SetUp();
396 if (ret != DH_SUCCESS) {
397 DHLOGE("set up av sender engine failed.");
398 return ERR_DH_AV_TRANS_SETUP_FAILED;
399 }
400 ret = senderAdapter_->Start();
401 if (ret != DH_SUCCESS) {
402 DHLOGE("start av sender engine failed.");
403 return ERR_DH_AV_TRANS_START_FAILED;
404 }
405 return DH_SUCCESS;
406 }
407
StopSenderEngine()408 int32_t DScreen::StopSenderEngine()
409 {
410 DHLOGI("StopSenderEngine, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
411 GetAnonyString(dhId_).c_str());
412 if (senderAdapter_ == nullptr) {
413 DHLOGE("av transport sender adapter is null.");
414 return ERR_DH_AV_TRANS_NULL_VALUE;
415 }
416
417 json paramJson;
418 paramJson[KEY_DEV_ID] = devId_;
419 paramJson[KEY_DH_ID] = dhId_;
420
421 auto avMessage = std::make_shared<AVTransMessage>(DScreenMsgType::STOP_MIRROR, paramJson.dump(), devId_);
422 senderAdapter_->SendMessageToRemote(avMessage);
423
424 int32_t ret = senderAdapter_->Stop();
425 if (ret != DH_SUCCESS) {
426 DHLOGE("stop av sender adapter failed.");
427 return ERR_DH_AV_TRANS_STOP_FAILED;
428 }
429 ret = senderAdapter_->Release();
430 if (ret != DH_SUCCESS) {
431 DHLOGE("release av sender adapter failed.");
432 return ERR_DH_AV_TRANS_STOP_FAILED;
433 }
434 return DH_SUCCESS;
435 }
436
ChooseParameter(std::string & codecType,std::string & pixelFormat)437 void DScreen::ChooseParameter(std::string &codecType, std::string &pixelFormat)
438 {
439 if (videoParam_->GetCodecType() == VIDEO_CODEC_TYPE_VIDEO_H265) {
440 codecType = MIME_VIDEO_H265;
441 } else if (videoParam_->GetCodecType() == VIDEO_CODEC_TYPE_VIDEO_H264) {
442 codecType = MIME_VIDEO_H264;
443 } else {
444 codecType = MIME_VIDEO_RAW;
445 }
446 if (videoParam_->GetVideoFormat() == VIDEO_DATA_FORMAT_YUVI420) {
447 pixelFormat = VIDEO_FORMAT_YUVI420;
448 } else if (videoParam_->GetVideoFormat() == VIDEO_DATA_FORMAT_NV12) {
449 pixelFormat = VIDEO_FORMAT_NV12;
450 } else if (videoParam_->GetVideoFormat() == VIDEO_DATA_FORMAT_NV21) {
451 pixelFormat = VIDEO_FORMAT_NV21;
452 } else {
453 pixelFormat = VIDEO_FORMAT_RGBA8888;
454 }
455 senderAdapter_->SetParameter(AVTransTag::VIDEO_CODEC_TYPE, codecType);
456 senderAdapter_->SetParameter(AVTransTag::VIDEO_PIXEL_FORMAT, pixelFormat);
457 senderAdapter_->SetParameter(AVTransTag::VIDEO_WIDTH, std::to_string(videoParam_->GetVideoWidth()));
458 senderAdapter_->SetParameter(AVTransTag::VIDEO_HEIGHT, std::to_string(videoParam_->GetVideoHeight()));
459 senderAdapter_->SetParameter(AVTransTag::VIDEO_FRAME_RATE, std::to_string(videoParam_->GetFps()));
460 senderAdapter_->SetParameter(AVTransTag::VIDEO_BIT_RATE, std::to_string(BIT_RATE));
461 }
462
SetUp()463 int32_t DScreen::SetUp()
464 {
465 DHLOGI("SetUp, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str());
466 if (senderAdapter_ == nullptr) {
467 DHLOGE("av transport sender adapter is null.");
468 return ERR_DH_AV_TRANS_NULL_VALUE;
469 }
470 if (videoParam_ == nullptr) {
471 DHLOGE("videoParam is nullptr.");
472 return ERR_DH_SCREEN_SA_VALUE_NOT_INIT;
473 }
474 auto mapRelation = ScreenMgrAdapter::GetInstance().GetMapRelation(screenId_);
475 if (mapRelation == nullptr) {
476 DHLOGE("get map relation failed.");
477 return ERR_DH_AV_TRANS_SETUP_FAILED;
478 }
479 DisplayRect displayRect = mapRelation->GetDisplayRect();
480 videoParam_->SetVideoWidth(displayRect.width);
481 videoParam_->SetVideoHeight(displayRect.height);
482
483 json paramJson;
484 paramJson[KEY_DH_ID] = dhId_;
485 paramJson[KEY_SCREEN_ID] = screenId_;
486 paramJson[KEY_VIDEO_PARAM] = *videoParam_;
487 paramJson[KEY_MAPRELATION] = *mapRelation;
488
489 auto avMessage = std::make_shared<AVTransMessage>(DScreenMsgType::START_MIRROR, paramJson.dump(), devId_);
490 int32_t ret = senderAdapter_->SendMessageToRemote(avMessage);
491 if (ret != DH_SUCCESS) {
492 DHLOGE("send message to remote engine failed.");
493 return ret;
494 }
495
496 ret = WaitForSinkStarted();
497 if (ret != DH_SUCCESS) {
498 DHLOGE("send message to start remote device engine failed.");
499 return ret;
500 }
501
502 std::string codecType;
503 std::string pixelFormat;
504 ChooseParameter(codecType, pixelFormat);
505 return senderAdapter_->SetParameter(AVTransTag::ENGINE_READY, OWNER_NAME_D_SCREEN);
506 }
507
WaitForSinkStarted()508 int32_t DScreen::WaitForSinkStarted()
509 {
510 std::unique_lock<std::mutex> lock(waitSinkMtx_);
511 auto status = waitSinkCondVar_.wait_for(lock, std::chrono::milliseconds(WAIT_TIMEOUT_MS),
512 [this]() { return sinkStartSuccess_.load(); });
513 if (!status) {
514 DHLOGE("wait for sink device engine start timeout");
515 return ERR_DH_AV_TRANS_TIMEOUT;
516 }
517 if (!sinkStartSuccess_.load()) {
518 DHLOGE("start sink device engine failed");
519 return ERR_DH_AV_TRANS_SINK_START_FAILED;
520 }
521 return DH_SUCCESS;
522 }
523
NegotiateCodecType(const std::string & rmtDecoderStr)524 int32_t DScreen::NegotiateCodecType(const std::string &rmtDecoderStr)
525 {
526 DHLOGI("Start NegotiateCodecType, remote decoder: %{public}s", rmtDecoderStr.c_str());
527 cJSON *rmtDecoderJson = cJSON_Parse(rmtDecoderStr.c_str());
528 if (rmtDecoderJson == nullptr) {
529 DHLOGE("remote Decoder Json is invalid.");
530 return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
531 }
532
533 std::vector<VideoDecoder> rmtVideoDecoders;
534 FromJson<VideoDecoder>(VIDEO_DECODERS, rmtDecoderJson, rmtVideoDecoders);
535 cJSON_Delete(rmtDecoderJson);
536
537 std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = DScreenFwkKit::GetInstance().GetDHFwkKit();
538 if (dhFwkKit == nullptr) {
539 DHLOGE("Get DhFwkKit return null");
540 return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
541 }
542 std::string localVideoEncodersJsonStr =
543 dhFwkKit->QueryLocalSysSpec(QueryLocalSysSpecType::HISTREAMER_VIDEO_ENCODER);
544 if (localVideoEncodersJsonStr.empty()) {
545 DHLOGE("Query local Codec info failed");
546 return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
547 }
548 DHLOGI("DScreen Negotiate QueryVideoEncoderAbility info: %{public}s", localVideoEncodersJsonStr.c_str());
549
550 cJSON *localVideoEncodersJson = cJSON_Parse(localVideoEncodersJsonStr.c_str());
551 if (localVideoEncodersJson == nullptr) {
552 DHLOGE("localVideoEncodersJson is invalid.");
553 return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
554 }
555
556 std::vector<VideoEncoder> localVideoEncoders;
557 FromJson<VideoEncoder>(VIDEO_ENCODERS, localVideoEncodersJson, localVideoEncoders);
558 cJSON_Delete(localVideoEncodersJson);
559
560 return ChooseCodecType(localVideoEncoders, rmtVideoDecoders);
561 }
562
ChooseCodecType(const std::vector<VideoEncoder> & localVideoEncoders,const std::vector<VideoDecoder> & rmtVideoDecoders)563 int32_t DScreen::ChooseCodecType(const std::vector<VideoEncoder> &localVideoEncoders,
564 const std::vector<VideoDecoder> &rmtVideoDecoders)
565 {
566 std::vector<std::string> codecTypeCandidates;
567 for (const auto &rmtDec : rmtVideoDecoders) {
568 for (const auto &locEnc : localVideoEncoders) {
569 std::pair<std::string, std::string> comb = {locEnc.name, rmtDec.name};
570 if (CODECS_MAP.find(comb) != CODECS_MAP.end()) {
571 std::string codec = CODECS_MAP.at(comb);
572 DHLOGI("Find match comb, local encoder: %{public}s, remote decoder: %{public}s, codec: %{public}s",
573 locEnc.name.c_str(), rmtDec.name.c_str(), codec.c_str());
574 codecTypeCandidates.push_back(codec);
575 }
576 }
577 }
578 if (std::find(codecTypeCandidates.begin(), codecTypeCandidates.end(),
579 CODEC_NAME_H265) != codecTypeCandidates.end()) {
580 videoParam_->SetCodecType(VIDEO_CODEC_TYPE_VIDEO_H265);
581 videoParam_->SetVideoFormat(VIDEO_DATA_FORMAT_NV12);
582 } else if (std::find(codecTypeCandidates.begin(), codecTypeCandidates.end(),
583 CODEC_NAME_H264) != codecTypeCandidates.end()) {
584 videoParam_->SetCodecType(VIDEO_CODEC_TYPE_VIDEO_H264);
585 videoParam_->SetVideoFormat(VIDEO_DATA_FORMAT_NV12);
586 } else {
587 DHLOGI("codec type not support.");
588 return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
589 }
590 return DH_SUCCESS;
591 }
592
TaskThreadLoop()593 void DScreen::TaskThreadLoop()
594 {
595 DHLOGI("DScreen taskThread start. devId: %{public}s, dhId: %{public}s", GetAnonyString(devId_).c_str(),
596 GetAnonyString(dhId_).c_str());
597 while (taskThreadRunning_) {
598 watchdogFlag_ = true;
599 std::shared_ptr<Task> task;
600 {
601 std::unique_lock<std::mutex> lock(taskQueueMtx_);
602 auto status = taskQueueCond_.wait_for(lock, std::chrono::seconds(TASK_WAIT_SECONDS),
603 [this]() { return !taskQueue_.empty(); });
604 if (!status) {
605 DHLOGD("Task queue wait timeout after %{public}d seconds.", TASK_WAIT_SECONDS);
606 continue;
607 }
608 if (taskQueue_.empty()) {
609 continue;
610 }
611 task = taskQueue_.front();
612 taskQueue_.pop();
613 }
614 if (task == nullptr) {
615 DHLOGD("task is null.");
616 continue;
617 }
618 DHLOGD("run task, task queue size: %{public}zu", taskQueue_.size());
619 HandleTask(task);
620 }
621 }
622
CheckJsonData(const json & attrJson)623 bool DScreen::CheckJsonData(const json &attrJson)
624 {
625 if (attrJson.is_discarded()) {
626 DHLOGE("enable param json is invalid.");
627 return false;
628 }
629 if (!IsUInt32(attrJson, KEY_SCREEN_WIDTH) || !IsUInt32(attrJson, KEY_SCREEN_HEIGHT) ||
630 !attrJson.contains(KEY_CODECTYPE)) {
631 DHLOGE("enable param is invalid.");
632 return false;
633 }
634 return true;
635 }
636
OnEngineEvent(DScreenEventType event,const std::string & content)637 void DScreen::OnEngineEvent(DScreenEventType event, const std::string &content)
638 {
639 (void)content;
640 if (event == DScreenEventType::ENGINE_ERROR) {
641 StopSenderEngine();
642 } else if (event == DScreenEventType::TRANS_CHANNEL_CLOSED) {
643 HandleDisconnect();
644 }
645 }
646
OnEngineMessage(const std::shared_ptr<AVTransMessage> & message)647 void DScreen::OnEngineMessage(const std::shared_ptr<AVTransMessage> &message)
648 {
649 if (message == nullptr) {
650 DHLOGE("received engine message is null.");
651 return;
652 }
653 DHLOGI("On sink device engine message received, message type =%{public}d.", message->type_);
654 if ((message->type_ == DScreenMsgType::START_MIRROR_SUCCESS) ||
655 (message->type_ == DScreenMsgType::START_MIRROR_FAIL)) {
656 sinkStartSuccess_ = (message->type_ == DScreenMsgType::START_MIRROR_SUCCESS);
657 waitSinkCondVar_.notify_one();
658 }
659 }
660
GetVideoParam()661 std::shared_ptr<VideoParam> DScreen::GetVideoParam()
662 {
663 return videoParam_;
664 }
665
SetState(DScreenState state)666 void DScreen::SetState(DScreenState state)
667 {
668 std::lock_guard<std::mutex> lock(stateMtx_);
669 curState_ = state;
670 }
671
GetState() const672 DScreenState DScreen::GetState() const
673 {
674 return curState_;
675 }
676
GetScreenId() const677 uint64_t DScreen::GetScreenId() const
678 {
679 return screenId_;
680 }
681
GetDHId() const682 std::string DScreen::GetDHId() const
683 {
684 return dhId_;
685 }
686
GetDevId() const687 std::string DScreen::GetDevId() const
688 {
689 return devId_;
690 }
691 } // namespace V2_0
692 } // namespace DistributedHardware
693 } // namespace OHOS