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