• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "dscreen.h"
17 
18 #include "avcodec_info.h"
19 #include "avcodec_list.h"
20 
21 #include "dscreen_constants.h"
22 #include "dscreen_errcode.h"
23 #include "dscreen_hisysevent.h"
24 #include "dscreen_json_util.h"
25 #include "dscreen_log.h"
26 #include "dscreen_util.h"
27 #include "screen_manager_adapter.h"
28 #include "screen_source_trans.h"
29 
30 namespace OHOS {
31 namespace DistributedHardware {
DScreen(const std::string & devId,const std::string & dhId,std::shared_ptr<IDScreenCallback> dscreenCallback)32 DScreen::DScreen(const std::string &devId, const std::string &dhId,
33     std::shared_ptr<IDScreenCallback> dscreenCallback)
34 {
35     DHLOGD("DScreen construct, devId: %s, dhId: %s", GetAnonyString(devId).c_str(),
36         GetAnonyString(dhId).c_str());
37     devId_ = devId;
38     dhId_ = dhId;
39     dscreenCallback_ = dscreenCallback;
40     SetState(DISABLED);
41     taskThreadRunning_ = true;
42     taskQueueThread_ = std::thread(&DScreen::TaskThreadLoop, this);
43 }
44 
~DScreen()45 DScreen::~DScreen()
46 {
47     DHLOGD("DScreen deconstruct, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
48         GetAnonyString(dhId_).c_str());
49     taskThreadRunning_ = false;
50     taskQueueCond_.notify_all();
51     if (taskQueueThread_.joinable()) {
52         taskQueueThread_.join();
53     }
54     int32_t ret = DH_SUCCESS;
55     if (sourceTrans_ != nullptr) {
56         ret = sourceTrans_->Release();
57     }
58     if (ret != DH_SUCCESS) {
59         DHLOGE("source trans release failed. ret: %d", ret);
60     }
61 
62     if (screenId_ != SCREEN_ID_INVALID) {
63         ret = ScreenMgrAdapter::GetInstance().RemoveVirtualScreen(screenId_);
64     }
65 
66     if (ret != DH_SUCCESS) {
67         DHLOGE("remove virtual screen failed.");
68     }
69     videoParam_ = nullptr;
70     sourceTrans_ = nullptr;
71     DHLOGD("DScreen deconstruct end.");
72 }
73 
OnTransError(int32_t err,const std::string & content)74 void DScreen::OnTransError(int32_t err, const std::string &content)
75 {
76     DHLOGD("OnTransError, err: %d", err);
77     AddTask(std::make_shared<Task>(TaskType::TASK_DISCONNECT, ""));
78     ScreenMgrAdapter::GetInstance().RemoveScreenFromGroup(screenId_);
79 }
80 
SetVideoParam(std::shared_ptr<VideoParam> & videoParam)81 void DScreen::SetVideoParam(std::shared_ptr<VideoParam> &videoParam)
82 {
83     videoParam_ = videoParam;
84 }
85 
GetVideoParam()86 std::shared_ptr<VideoParam> DScreen::GetVideoParam()
87 {
88     return videoParam_;
89 }
90 
SetState(DScreenState state)91 void DScreen::SetState(DScreenState state)
92 {
93     std::lock_guard<std::mutex> lock(stateMtx_);
94     curState_ = state;
95 }
96 
GetState() const97 DScreenState DScreen::GetState() const
98 {
99     return curState_;
100 }
101 
GetScreenId() const102 uint64_t DScreen::GetScreenId() const
103 {
104     return screenId_;
105 }
106 
GetDHId() const107 std::string DScreen::GetDHId() const
108 {
109     return dhId_;
110 }
111 
GetDevId() const112 std::string DScreen::GetDevId() const
113 {
114     return devId_;
115 }
116 
AddTask(const std::shared_ptr<Task> & task)117 int32_t DScreen::AddTask(const std::shared_ptr<Task> &task)
118 {
119     DHLOGI("DScreen::AddTask, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
120         GetAnonyString(dhId_).c_str());
121     if (task == nullptr) {
122         DHLOGE("AddTask, task is invalid.");
123         return ERR_DH_SCREEN_SA_DSCREEN_TASK_NOT_VALID;
124     }
125     DHLOGI("AddTask, task type: %d", task->GetTaskType());
126     {
127         std::lock_guard<std::mutex> lock(taskQueueMtx_);
128         taskQueue_.push(task);
129     }
130     taskQueueCond_.notify_all();
131     return DH_SUCCESS;
132 }
133 
TaskThreadLoop()134 void DScreen::TaskThreadLoop()
135 {
136     DHLOGI("DScreen taskThread start. devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
137         GetAnonyString(dhId_).c_str());
138     while (taskThreadRunning_) {
139         std::shared_ptr<Task> task;
140         {
141             std::unique_lock<std::mutex> lock(taskQueueMtx_);
142             taskQueueCond_.wait_for(lock, std::chrono::seconds(TASK_WAIT_SECONDS),
143                 [this]() { return !taskQueue_.empty(); });
144             if (taskQueue_.empty()) {
145                 continue;
146             }
147             task = taskQueue_.front();
148             taskQueue_.pop();
149         }
150 
151         if (task == nullptr) {
152             DHLOGD("task is null.");
153             continue;
154         }
155 
156         DHLOGD("run task, task queue size: %zu", taskQueue_.size());
157         HandleTask(task);
158     }
159 }
160 
HandleTask(const std::shared_ptr<Task> & task)161 void DScreen::HandleTask(const std::shared_ptr<Task> &task)
162 {
163     int32_t taskType = task->GetTaskType();
164     DHLOGI("HandleTask, devId: %s, dhId: %s, task type: %d", GetAnonyString(devId_).c_str(),
165         GetAnonyString(dhId_).c_str(), taskType);
166     switch (taskType) {
167         case TaskType::TASK_ENABLE:
168             HandleEnable(task->GetTaskParam(), task->GetTaskId());
169             break;
170         case TaskType::TASK_DISABLE:
171             HandleDisable(task->GetTaskId());
172             break;
173         case TaskType::TASK_CONNECT:
174             HandleConnect();
175             break;
176         case TaskType::TASK_DISCONNECT:
177             HandleDisconnect();
178             break;
179         default:
180             DHLOGD("task type unkown.");
181     }
182 }
183 
HandleEnable(const std::string & param,const std::string & taskId)184 void DScreen::HandleEnable(const std::string &param, const std::string &taskId)
185 {
186     DHLOGI("HandleEnable, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str());
187     if (curState_ == ENABLED || curState_ == ENABLING || curState_ == CONNECTING || curState_ == CONNECTED) {
188         dscreenCallback_->OnRegResult(shared_from_this(), taskId, DH_SUCCESS, "dscreen enable success.");
189         return;
190     }
191 
192     SetState(ENABLING);
193     if (videoParam_ == nullptr) {
194         videoParam_ = std::make_shared<VideoParam>();
195     }
196 
197     json attrJson = json::parse(param, nullptr, false);
198     int32_t ret = CheckJsonData(attrJson);
199     if (ret != DH_SUCCESS) {
200         DHLOGE("check json data failed.");
201         dscreenCallback_->OnRegResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_ENABLE_FAILED,
202             "enable param json is invalid.");
203         ReportRegisterFail(DSCREEN_REGISTER_FAIL, ERR_DH_SCREEN_SA_ENABLE_FAILED, GetAnonyString(devId_).c_str(),
204             GetAnonyString(dhId_).c_str(), "check json data failed.");
205         return;
206     }
207 
208     videoParam_->SetScreenWidth(attrJson[KEY_SCREEN_WIDTH].get<uint32_t>());
209     videoParam_->SetScreenHeight(attrJson[KEY_SCREEN_HEIGHT].get<uint32_t>());
210 
211     // negotiate codecType
212     ret = NegotiateCodecType(attrJson[KEY_CODECTYPE]);
213     if (ret != DH_SUCCESS) {
214         DHLOGE("negotiate codec type failed.");
215         dscreenCallback_->OnRegResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_ENABLE_FAILED,
216             "negotiate codec type failed.");
217         ReportRegisterFail(DSCREEN_REGISTER_FAIL, ERR_DH_SCREEN_SA_ENABLE_FAILED, GetAnonyString(devId_).c_str(),
218             GetAnonyString(dhId_).c_str(), "negotiate codec type failed.");
219         return;
220     }
221 
222     uint64_t screenId = ScreenMgrAdapter::GetInstance().CreateVirtualScreen(devId_, dhId_, videoParam_);
223     if (screenId == SCREEN_ID_INVALID) {
224         DHLOGE("create virtual screen failed.");
225         dscreenCallback_->OnRegResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_ENABLE_FAILED,
226             "create virtual screen failed.");
227         ReportRegisterFail(DSCREEN_REGISTER_FAIL, ERR_DH_SCREEN_SA_ENABLE_FAILED, GetAnonyString(devId_).c_str(),
228             GetAnonyString(dhId_).c_str(), "create virtual screen failed.");
229         return;
230     }
231     screenId_ = screenId;
232     SetState(ENABLED);
233     dscreenCallback_->OnRegResult(shared_from_this(), taskId, DH_SUCCESS, "dscreen enable success.");
234     ReportRegisterScreenEvent(DSCREEN_REGISTER, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
235         "dscreen enable success.");
236 }
237 
CheckJsonData(json & attrJson)238 int32_t DScreen::CheckJsonData(json &attrJson)
239 {
240     if (attrJson.is_discarded()) {
241         DHLOGE("enable param json is invalid.");
242         return ERR_DH_SCREEN_SA_ENABLE_JSON_ERROR;
243     }
244 
245     if (!IsUInt32(attrJson, KEY_SCREEN_WIDTH) || !IsUInt32(attrJson, KEY_SCREEN_HEIGHT) ||
246         !IsString(attrJson, KEY_CODECTYPE)) {
247         DHLOGE("enable param is invalid.");
248         return ERR_DH_SCREEN_SA_ENABLE_JSON_ERROR;
249     }
250     return DH_SUCCESS;
251 }
252 
NegotiateCodecType(const std::string & remoteCodecInfoStr)253 int32_t DScreen::NegotiateCodecType(const std::string &remoteCodecInfoStr)
254 {
255     json remoteCodecArray = json::parse(remoteCodecInfoStr, nullptr, false);
256     if (remoteCodecArray.is_discarded() || !remoteCodecArray.is_array()) {
257         DHLOGE("remoteCodecInfoStrjson is invalid.");
258         return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
259     }
260 
261     std::vector<std::string> localCodecArray;
262     // query local support encoder type
263     std::shared_ptr<Media::AVCodecList> codecList = Media::AVCodecListFactory::CreateAVCodecList();
264     if (codecList == nullptr) {
265         DHLOGE("codecList is nullptr.");
266         return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
267     }
268     std::vector<std::shared_ptr<Media::VideoCaps>> caps = codecList->GetVideoEncoderCaps();
269     for (const auto &cap : caps) {
270         std::shared_ptr<Media::AVCodecInfo> codecInfo = cap->GetCodecInfo();
271         if (codecInfo == nullptr) {
272             continue;
273         }
274         localCodecArray.push_back(codecInfo->GetName());
275     }
276 
277     std::vector<std::string> codecTypeCandidates;
278     for (const auto &remoteCodecType : remoteCodecArray) {
279         if (std::find(localCodecArray.begin(), localCodecArray.end(),
280             remoteCodecType) != localCodecArray.end()) {
281             codecTypeCandidates.push_back(remoteCodecType);
282         }
283     }
284 
285     if (std::find(codecTypeCandidates.begin(), codecTypeCandidates.end(),
286         CODEC_NAME_H264) != codecTypeCandidates.end()) {
287         videoParam_->SetCodecType(VIDEO_CODEC_TYPE_VIDEO_H264);
288         videoParam_->SetVideoFormat(VIDEO_DATA_FORMAT_NV12);
289     } else if (std::find(codecTypeCandidates.begin(), codecTypeCandidates.end(),
290         CODEC_NAME_MPEG4) != codecTypeCandidates.end()) {
291         videoParam_->SetCodecType(VIDEO_CODEC_TYPE_VIDEO_MPEG4);
292         videoParam_->SetVideoFormat(VIDEO_DATA_FORMAT_RGBA8888);
293     } else {
294         DHLOGI("codec type not support.");
295         return ERR_DH_SCREEN_SA_DSCREEN_NEGOTIATE_CODEC_FAIL;
296     }
297 
298     return DH_SUCCESS;
299 }
300 
HandleDisable(const std::string & taskId)301 void DScreen::HandleDisable(const std::string &taskId)
302 {
303     DHLOGI("HandleDisable, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str());
304     SetState(DISABLING);
305     int32_t ret = ScreenMgrAdapter::GetInstance().RemoveVirtualScreen(screenId_);
306     if (ret != DH_SUCCESS) {
307         DHLOGE("remove virtual screen failed.");
308         dscreenCallback_->OnUnregResult(shared_from_this(), taskId, ERR_DH_SCREEN_SA_DISABLE_FAILED,
309             "remove virtual screen failed.");
310         ReportUnRegisterFail(DSCREEN_UNREGISTER_FAIL, ERR_DH_SCREEN_SA_DISABLE_FAILED, GetAnonyString(devId_).c_str(),
311             GetAnonyString(dhId_).c_str(), "remove virtual screen failed.");
312         return;
313     }
314     SetState(DISABLED);
315     dscreenCallback_->OnUnregResult(shared_from_this(), taskId, DH_SUCCESS, "");
316     ReportUnRegisterScreenEvent(DSCREEN_UNREGISTER, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
317         "dscreen disable success.");
318 }
319 
HandleConnect()320 void DScreen::HandleConnect()
321 {
322     DHLOGI("HandleConnect, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
323         GetAnonyString(dhId_).c_str());
324 
325     int32_t ret = SetUp();
326     if (ret != DH_SUCCESS) {
327         SetState(ENABLED);
328         ScreenMgrAdapter::GetInstance().RemoveScreenFromGroup(screenId_);
329         DHLOGE("dScreen SetUp failed.");
330         return;
331     }
332 
333     ret = Start();
334     if (ret != DH_SUCCESS) {
335         SetState(ENABLED);
336         ScreenMgrAdapter::GetInstance().RemoveScreenFromGroup(screenId_);
337         DHLOGE("dScreen Start failed.");
338         return;
339     }
340     SetState(CONNECTED);
341     ReportScreenMirrorEvent(DSCREEN_PROJECT_START, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
342         "dscreen connect success");
343 }
344 
HandleDisconnect()345 void DScreen::HandleDisconnect()
346 {
347     DHLOGD("HandleDisconnect, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
348         GetAnonyString(dhId_).c_str());
349     if (curState_ != CONNECTED) {
350         DHLOGE("dscreen is not connected, cannot disconnect");
351         return;
352     }
353     SetState(DISCONNECTING);
354     int32_t ret = Stop();
355     if (ret != DH_SUCCESS) {
356         SetState(CONNECTED);
357         DHLOGE("dScreen Stop failed.");
358         return;
359     }
360     SetState(ENABLED);
361     ReportScreenMirrorEvent(DSCREEN_PROJECT_END, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
362         "dscreen disconnect success");
363 }
364 
SetUp()365 int32_t DScreen::SetUp()
366 {
367     DHLOGD("SetUp, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
368         GetAnonyString(dhId_).c_str());
369 
370     if (sourceTrans_ == nullptr) {
371         sourceTrans_ = std::make_shared<ScreenSourceTrans>();
372     }
373 
374     sourceTrans_->RegisterStateCallback(shared_from_this());
375     int32_t ret = sourceTrans_->SetUp(*videoParam_, *videoParam_, devId_);
376     if (ret != DH_SUCCESS) {
377         DHLOGE("source trans SetUp failed.");
378         return ret;
379     }
380 
381     sptr<OHOS::Surface> surface = sourceTrans_->GetImageSurface();
382     if (surface == nullptr) {
383         DHLOGE("DScreen SetUp failed.");
384         return ERR_DH_SCREEN_SA_DSCREEN_SETUP_FAILED;
385     }
386 
387     ScreenMgrAdapter::GetInstance().SetImageSurface(screenId_, surface);
388     DHLOGI("DScreen SetUp success.");
389     return DH_SUCCESS;
390 }
391 
Start()392 int32_t DScreen::Start()
393 {
394     DHLOGD("Start, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
395         GetAnonyString(dhId_).c_str());
396     if (sourceTrans_ == nullptr) {
397         DHLOGE("source trans not init.");
398         return ERR_DH_SCREEN_SA_SOURCETRANS_NOT_INIT;
399     }
400 
401     int32_t ret = sourceTrans_->Start();
402     if (ret != DH_SUCCESS) {
403         DHLOGE("source trans start failed.");
404         return ret;
405     }
406     return DH_SUCCESS;
407 }
408 
Stop()409 int32_t DScreen::Stop()
410 {
411     DHLOGD("Stop, devId: %s, dhId: %s", GetAnonyString(devId_).c_str(),
412         GetAnonyString(dhId_).c_str());
413     if (sourceTrans_ == nullptr) {
414         DHLOGE("source trans not init.");
415         return ERR_DH_SCREEN_SA_SOURCETRANS_NOT_INIT;
416     }
417 
418     int32_t ret = sourceTrans_->Stop();
419     if (ret != DH_SUCCESS) {
420         DHLOGE("source trans stop failed.");
421         return ret;
422     }
423 
424     ret = sourceTrans_->Release();
425     if (ret != DH_SUCCESS) {
426         DHLOGE("source trans release failed.");
427         return ret;
428     }
429 
430     sourceTrans_ = nullptr;
431     return DH_SUCCESS;
432 }
433 } // namespace DistributedHardware
434 } // namespace OHOS