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