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 ¶m)
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