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 &param, 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 &param, 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