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