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