• 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 "screen_source_trans.h"
17 
18 #include <chrono>
19 
20 #include "dscreen_errcode.h"
21 #include "dscreen_hisysevent.h"
22 #include "dscreen_hitrace.h"
23 #include "dscreen_log.h"
24 #include "image_source_processor.h"
25 #include "screen_data_channel_impl.h"
26 
27 namespace OHOS {
28 namespace DistributedHardware {
SetUp(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)29 int32_t ScreenSourceTrans::SetUp(const VideoParam &localParam, const VideoParam &remoteParam,
30     const std::string &peerDevId)
31 {
32     DHLOGI("%s: SetUp.", LOG_TAG);
33     int32_t ret = CheckTransParam(localParam, remoteParam, peerDevId);
34     if (ret != DH_SUCCESS) {
35         DHLOGE("%s: SetUp failed param error ret: %d.", LOG_TAG, ret);
36         return ret;
37     }
38 
39     ret = InitScreenTrans(localParam, remoteParam, peerDevId);
40     if (ret != DH_SUCCESS) {
41         DHLOGE("%s: SetUp failed ret: %d.", LOG_TAG, ret);
42         return ret;
43     }
44 
45     DHLOGI("%s: SetUp success.", LOG_TAG);
46     return DH_SUCCESS;
47 }
48 
Release()49 int32_t ScreenSourceTrans::Release()
50 {
51     DHLOGI("%s: Release.", LOG_TAG);
52     if (imageProcessor_ == nullptr || screenChannel_ == nullptr) {
53         DHLOGE("%s: Processor or channel is null, Setup first.", LOG_TAG);
54         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
55     }
56 
57     int32_t ret = imageProcessor_->ReleaseImageProcessor();
58     if (ret != DH_SUCCESS) {
59         DHLOGD("%s: Release image processor failed ret: %d.", LOG_TAG, ret);
60     }
61     imageProcessor_ = nullptr;
62 
63     StartTrace(DSCREEN_HITRACE_LABEL, DSCREEN_SOURCE_RELEASE_SESSION_START);
64     ret = screenChannel_->ReleaseSession();
65     FinishTrace(DSCREEN_HITRACE_LABEL);
66     if (ret != DH_SUCCESS) {
67         DHLOGD("%s: Release channel session failed ret: %d.", LOG_TAG, ret);
68     }
69     screenChannel_ = nullptr;
70 
71     std::lock_guard<std::mutex> lck(dataQueueMtx_);
72     while (!dataQueue_.empty()) {
73         dataQueue_.pop();
74     }
75 
76     DHLOGI("%s: Release success.", LOG_TAG);
77     return DH_SUCCESS;
78 }
79 
Start()80 int32_t ScreenSourceTrans::Start()
81 {
82     DHLOGI("%s: Start.", LOG_TAG);
83     if (imageProcessor_ == nullptr || screenChannel_ == nullptr) {
84         DHLOGE("%s: Processor or channel is null, Setup first.", LOG_TAG);
85         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
86     }
87 
88     StartTrace(DSCREEN_HITRACE_LABEL, DSCREEN_SOURCE_OPEN_SESSION_START);
89     int32_t ret = screenChannel_->OpenSession();
90     if (ret != DH_SUCCESS) {
91         DHLOGE("%s: Open channel session failed ret: %d.", LOG_TAG, ret);
92         return ret;
93     }
94 
95     DHLOGI("%s: Wait for channel session opened.", LOG_TAG);
96     std::unique_lock<std::mutex> lck(sessionMtx_);
97     auto status =
98         sessionCond_.wait_for(lck, std::chrono::seconds(SESSION_WAIT_SECONDS), [this]() { return isChannelReady_; });
99     if (!status) {
100         DHLOGE("%s: Open channel session timeout(%ds).", LOG_TAG, SESSION_WAIT_SECONDS);
101         return ERR_DH_SCREEN_TRANS_TIMEOUT;
102     }
103 
104     DHLOGI("%s: Start success.", LOG_TAG);
105     FinishTrace(DSCREEN_HITRACE_LABEL);
106     return DH_SUCCESS;
107 }
108 
Stop()109 int32_t ScreenSourceTrans::Stop()
110 {
111     DHLOGI("%s: Stop.", LOG_TAG);
112     if (imageProcessor_ == nullptr || screenChannel_ == nullptr) {
113         DHLOGE("%s: Processor or channel is null, Setup first.", LOG_TAG);
114         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
115     }
116 
117     bool stopStatus = true;
118     int32_t ret = imageProcessor_->StopImageProcessor();
119     if (ret != DH_SUCCESS) {
120         DHLOGD("%s: Stop image processor failed ret: %d.", LOG_TAG, ret);
121         stopStatus = false;
122     }
123 
124     StartTrace(DSCREEN_HITRACE_LABEL, DSCREEN_SOURCE_CLOSE_SESSION_START);
125     ret = screenChannel_->CloseSession();
126     FinishTrace(DSCREEN_HITRACE_LABEL);
127     if (ret != DH_SUCCESS) {
128         DHLOGD("%s: Close Session failed ret: %d.", LOG_TAG, ret);
129         stopStatus = false;
130     }
131     isChannelReady_ = false;
132     if (sendDataThread_.joinable()) {
133         sendDataThread_.join();
134     }
135 
136     if (!stopStatus) {
137         DHLOGE("%s: Stop source trans failed.", LOG_TAG);
138         return ERR_DH_SCREEN_TRANS_ERROR;
139     }
140     DHLOGI("%s: Stop success.", LOG_TAG);
141     return DH_SUCCESS;
142 }
143 
RegisterStateCallback(const std::shared_ptr<IScreenSourceTransCallback> & callback)144 int32_t ScreenSourceTrans::RegisterStateCallback(const std::shared_ptr<IScreenSourceTransCallback> &callback)
145 {
146     DHLOGI("%s:RegisterStateCallback.", LOG_TAG);
147     if (callback == nullptr) {
148         DHLOGE("%s: Trans callback is null.", LOG_TAG);
149         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
150     }
151     transCallback_ = callback;
152 
153     return DH_SUCCESS;
154 }
155 
GetImageSurface()156 sptr<Surface> &ScreenSourceTrans::GetImageSurface()
157 {
158     DHLOGI("%s:GetImageSurface.", LOG_TAG);
159     return encoderSurface_;
160 }
161 
CheckVideoParam(const VideoParam & param)162 int32_t ScreenSourceTrans::CheckVideoParam(const VideoParam &param)
163 {
164     if ((param.GetCodecType() != VIDEO_CODEC_TYPE_VIDEO_H264) &&
165         (param.GetCodecType() != VIDEO_CODEC_TYPE_VIDEO_H265) &&
166         (param.GetCodecType() != VIDEO_CODEC_TYPE_VIDEO_MPEG4)) {
167         DHLOGE("%s: Invalid codec type.", LOG_TAG);
168         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
169     }
170 
171     if ((param.GetVideoFormat() != VIDEO_DATA_FORMAT_YUVI420) &&
172         (param.GetVideoFormat() != VIDEO_DATA_FORMAT_NV12) &&
173         (param.GetVideoFormat() != VIDEO_DATA_FORMAT_NV21) &&
174         (param.GetVideoFormat() != VIDEO_DATA_FORMAT_RGBA8888)) {
175         DHLOGE("%s: Invalid video data format.", LOG_TAG);
176         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
177     }
178 
179     if ((param.GetVideoWidth() > DSCREEN_MAX_VIDEO_DATA_WIDTH) ||
180         (param.GetVideoHeight() > DSCREEN_MAX_VIDEO_DATA_HEIGHT)) {
181         DHLOGE("%s: Invalid video data size.", LOG_TAG);
182         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
183     }
184 
185     if ((param.GetScreenWidth() > DSCREEN_MAX_SCREEN_DATA_WIDTH) ||
186         (param.GetScreenHeight() > DSCREEN_MAX_SCREEN_DATA_HEIGHT)) {
187         DHLOGE("%s: Invalid screen data size.", LOG_TAG);
188         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
189     }
190 
191     return DH_SUCCESS;
192 }
193 
CheckTransParam(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)194 int32_t ScreenSourceTrans::CheckTransParam(const VideoParam &localParam, const VideoParam &remoteParam,
195     const std::string &peerDevId)
196 {
197     DHLOGI("%s:CheckTransParam.", LOG_TAG);
198     if (peerDevId.empty()) {
199         DHLOGE("%s: Remote device id is null.", LOG_TAG);
200         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
201     }
202 
203     int32_t ret = CheckVideoParam(localParam);
204     if (ret != DH_SUCCESS) {
205         DHLOGE("%s: check localParam param failed.", LOG_TAG);
206         return ret;
207     }
208 
209     ret = CheckVideoParam(remoteParam);
210     if (ret != DH_SUCCESS) {
211         DHLOGE("%s: check remoteParam param failed.", LOG_TAG);
212         return ret;
213     }
214 
215     DHLOGI("%s: Local: codecType(%u), videoFormat(%u), videoSize(%ux%u), screenSize(%ux%u).", LOG_TAG,
216         localParam.GetCodecType(), localParam.GetVideoFormat(), localParam.GetVideoWidth(),
217         localParam.GetVideoHeight(), localParam.GetScreenWidth(), localParam.GetScreenHeight());
218     DHLOGI("%s: Remote: codecType(%u), videoFormat(%u), videoSize(%ux%u), screenSize(%ux%u).", LOG_TAG,
219         remoteParam.GetCodecType(), remoteParam.GetVideoFormat(), remoteParam.GetVideoWidth(),
220         remoteParam.GetVideoHeight(), remoteParam.GetScreenWidth(), remoteParam.GetScreenHeight());
221     return DH_SUCCESS;
222 }
223 
InitScreenTrans(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)224 int32_t ScreenSourceTrans::InitScreenTrans(const VideoParam &localParam, const VideoParam &remoteParam,
225     const std::string &peerDevId)
226 {
227     DHLOGI("%s:InitScreenTrans.", LOG_TAG);
228     screenChannel_ = std::make_shared<ScreenDataChannelImpl>(peerDevId);
229 
230     int32_t ret = RegisterChannelListener();
231     if (ret != DH_SUCCESS) {
232         DHLOGE("%s: Register channel listener failed ret: %d.", LOG_TAG, ret);
233         screenChannel_ = nullptr;
234         return ret;
235     }
236 
237     imageProcessor_ = std::make_shared<ImageSourceProcessor>();
238 
239     ret = RegisterProcessorListener(localParam, remoteParam);
240     if (ret != DH_SUCCESS) {
241         DHLOGE("%s: Register data processor listener failed ret: %d.", LOG_TAG, ret);
242         screenChannel_ = nullptr;
243         imageProcessor_ = nullptr;
244         return ret;
245     }
246 
247     return DH_SUCCESS;
248 }
249 
RegisterChannelListener()250 int32_t ScreenSourceTrans::RegisterChannelListener()
251 {
252     DHLOGI("%s: RegisterChannelListener.", LOG_TAG);
253     std::shared_ptr<IScreenChannelListener> listener = shared_from_this();
254     if (listener == nullptr) {
255         DHLOGE("%s: Channel listener is null", LOG_TAG);
256         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
257     }
258 
259     if (screenChannel_ == nullptr) {
260         DHLOGE("%s: Channel is null", LOG_TAG);
261         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
262     }
263     int32_t ret = screenChannel_->CreateSession(listener);
264     if (ret != DH_SUCCESS) {
265         DHLOGE("%s: Create session failed ret: %d.", LOG_TAG);
266         ReportOptFail(DSCREEN_OPT_FAIL, ret, "dscreen source Create session failed.");
267         return ret;
268     }
269 
270     return DH_SUCCESS;
271 }
272 
RegisterProcessorListener(const VideoParam & localParam,const VideoParam & remoteParam)273 int32_t ScreenSourceTrans::RegisterProcessorListener(const VideoParam &localParam, const VideoParam &remoteParam)
274 {
275     DHLOGI("%s: RegisterProcessorListener.", LOG_TAG);
276     std::shared_ptr<IImageSourceProcessorListener> listener = shared_from_this();
277     if (listener == nullptr) {
278         DHLOGE("%s: Processor listener is null", LOG_TAG);
279         return ERR_DH_SCREEN_TRANS_ERROR;
280     }
281 
282     if (imageProcessor_ == nullptr) {
283         DHLOGE("%s: imageProcessor is null", LOG_TAG);
284         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
285     }
286     int32_t ret = imageProcessor_->ConfigureImageProcessor(localParam, remoteParam, listener);
287     if (ret != DH_SUCCESS) {
288         DHLOGE("%s: Config image processor failed ret: %d.", LOG_TAG, ret);
289         ReportOptFail(DSCREEN_OPT_FAIL, ret, "Config image processor failed.");
290         return ret;
291     }
292 
293     encoderSurface_ = imageProcessor_->GetImageSurface();
294     if (encoderSurface_ == nullptr) {
295         DHLOGE("%s: Surface is null.", LOG_TAG);
296         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
297     }
298 
299     return DH_SUCCESS;
300 }
301 
OnSessionOpened()302 void ScreenSourceTrans::OnSessionOpened()
303 {
304     DHLOGI("%s: OnChannelSessionOpened.", LOG_TAG);
305     if (imageProcessor_ == nullptr) {
306         DHLOGE("%s: imageProcessor is null", LOG_TAG);
307         return;
308     }
309     int32_t ret = imageProcessor_->StartImageProcessor();
310     if (ret != DH_SUCCESS) {
311         DHLOGE("%s: Start image processor failed ret: %d.", LOG_TAG, ret);
312         return;
313     }
314 
315     isChannelReady_ = true;
316     DHLOGI("%s: Start thread.", LOG_TAG);
317     sendDataThread_ = std::thread(&ScreenSourceTrans::FeedChannelData, this);
318 
319     std::unique_lock<std::mutex> lck(sessionMtx_);
320     sessionCond_.notify_all();
321 }
322 
OnSessionClosed()323 void ScreenSourceTrans::OnSessionClosed()
324 {
325     DHLOGI("%s: OnChannelSessionClosed.", LOG_TAG);
326     isChannelReady_ = false;
327     if (sendDataThread_.joinable()) {
328         sendDataThread_.join();
329     }
330 
331     std::shared_ptr<IScreenSourceTransCallback> callback = transCallback_.lock();
332     if (callback == nullptr) {
333         DHLOGE("%s: Trans callback is null.", LOG_TAG);
334         return;
335     }
336     callback->OnError(ERR_DH_SCREEN_TRANS_SESSION_CLOSED, "OnChannelSessionClosed");
337 }
338 
OnDataReceived(const std::shared_ptr<DataBuffer> & data)339 void ScreenSourceTrans::OnDataReceived(const std::shared_ptr<DataBuffer> &data)
340 {
341     (void) data;
342     DHLOGI("%s: OnChannelDataReceived source trans not support.", LOG_TAG);
343 }
344 
OnImageProcessDone(const std::shared_ptr<DataBuffer> & data)345 void ScreenSourceTrans::OnImageProcessDone(const std::shared_ptr<DataBuffer> &data)
346 {
347     DHLOGD("%s: OnProcessorDataReceived received data from data processor.", LOG_TAG);
348     std::lock_guard<std::mutex> lck(dataQueueMtx_);
349     while (dataQueue_.size() >= DATA_QUEUE_MAX_SIZE) {
350         DHLOGE("%s: Data queue overflow.", LOG_TAG);
351         dataQueue_.pop();
352     }
353     dataQueue_.push(data);
354     dataCond_.notify_all();
355 }
356 
OnProcessorStateNotify(int32_t state)357 void ScreenSourceTrans::OnProcessorStateNotify(int32_t state)
358 {
359     DHLOGI("%s:OnProcessorStateNotify.", LOG_TAG);
360     std::shared_ptr<IScreenSourceTransCallback> callback = transCallback_.lock();
361     if (callback == nullptr) {
362         DHLOGE("%s: Trans callback is null.", LOG_TAG);
363         return;
364     }
365     callback->OnError(state, "OnProcessorStateNotify");
366 }
367 
FeedChannelData()368 void ScreenSourceTrans::FeedChannelData()
369 {
370     while (isChannelReady_) {
371         std::shared_ptr<DataBuffer> screenData;
372         {
373             std::unique_lock<std::mutex> lock(dataQueueMtx_);
374             dataCond_.wait_for(lock, std::chrono::seconds(DATA_WAIT_SECONDS), [this]() { return !dataQueue_.empty(); });
375             if (dataQueue_.empty()) {
376                 DHLOGD("%s:Data queue is empty.", LOG_TAG);
377                 continue;
378             }
379             screenData = dataQueue_.front();
380             dataQueue_.pop();
381         }
382 
383         if (screenChannel_ == nullptr) {
384             DHLOGE("%s: Channel is null", LOG_TAG);
385             return;
386         }
387         if (screenData == nullptr) {
388             DHLOGE("%s: Screen data is null", LOG_TAG);
389             continue;
390         }
391 
392         DHLOGD("%s: FeedChannelData.", LOG_TAG);
393         int32_t ret = screenChannel_->SendData(screenData);
394         if (ret != DH_SUCCESS) {
395             DHLOGD("%s:Send data failed.", LOG_TAG);
396         }
397         DHLOGD("%s: FeedChannelData success.", LOG_TAG);
398     }
399 }
400 } // namespace DistributedHardware
401 } // namespace OHOS