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