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_sink_trans.h"
17 
18 #include "distributed_hardware_errno.h"
19 #include "dscreen_errcode.h"
20 #include "dscreen_fwkkit.h"
21 #include "dscreen_hisysevent.h"
22 #include "dscreen_hitrace.h"
23 #include "dscreen_log.h"
24 #include "image_sink_processor.h"
25 #include "screen_data_channel_impl.h"
26 namespace OHOS {
27 namespace DistributedHardware {
SetUp(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)28 int32_t ScreenSinkTrans::SetUp(const VideoParam &localParam, const VideoParam &remoteParam,
29     const std::string &peerDevId)
30 {
31     DHLOGI("%{public}s: SetUp.", DSCREEN_LOG_TAG);
32     int32_t ret = CheckTransParam(localParam, remoteParam, peerDevId);
33     if (ret != DH_SUCCESS) {
34         DHLOGE("%{public}s: SetUp failed param error ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
35         return ret;
36     }
37 
38     ret = InitScreenTrans(localParam, remoteParam, peerDevId);
39     if (ret != DH_SUCCESS) {
40         DHLOGE("%{public}s: SetUp failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
41         return ret;
42     }
43 
44     DHLOGI("%{public}s: SetUp success.", DSCREEN_LOG_TAG);
45     return DH_SUCCESS;
46 }
47 
Release()48 int32_t ScreenSinkTrans::Release()
49 {
50     DHLOGI("%{public}s: Release.", DSCREEN_LOG_TAG);
51 
52     int32_t ret = 0;
53     if (imageProcessor_ != nullptr) {
54         ret = imageProcessor_->ReleaseImageProcessor();
55         if (ret != DH_SUCCESS) {
56             DHLOGW("%{public}s: Release image processor failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
57         }
58         imageProcessor_ = nullptr;
59     } else {
60         DHLOGI("%{public}s: Processor is null, Setup first.", DSCREEN_LOG_TAG);
61     }
62 
63     if (screenChannel_ != nullptr) {
64         StartTrace(DSCREEN_HITRACE_LABEL, DSCREEN_SINK_RELEASE_SESSION_START);
65         ret = screenChannel_->ReleaseSession();
66         FinishTrace(DSCREEN_HITRACE_LABEL);
67         if (ret != DH_SUCCESS) {
68             DHLOGW("%{public}s: Release channel session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
69         }
70         screenChannel_ = nullptr;
71     } else {
72         DHLOGI("%{public}s: Channel is null, Setup first.", DSCREEN_LOG_TAG);
73     }
74 
75     DHLOGI("%{public}s: Release success.", DSCREEN_LOG_TAG);
76     return DH_SUCCESS;
77 }
78 
Start()79 int32_t ScreenSinkTrans::Start()
80 {
81     DHLOGI("%{public}s: Start.", DSCREEN_LOG_TAG);
82     if (imageProcessor_ == nullptr) {
83         DHLOGE("%{public}s: Processor is null, Setup first.", DSCREEN_LOG_TAG);
84         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
85     }
86 
87     int32_t ret = imageProcessor_->StartImageProcessor();
88     if (ret != DH_SUCCESS) {
89         DHLOGE("%{public}s: Start image processor failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
90         return ret;
91     }
92 
93     DHLOGI("%{public}s: Start success.", DSCREEN_LOG_TAG);
94     return DH_SUCCESS;
95 }
96 
Stop()97 int32_t ScreenSinkTrans::Stop()
98 {
99     DHLOGI("%{public}s: Stop.", DSCREEN_LOG_TAG);
100 
101     int32_t ret = 0;
102     if (imageProcessor_ != nullptr) {
103         ret = imageProcessor_->StopImageProcessor();
104         if (ret != DH_SUCCESS) {
105             DHLOGW("%{public}s: Stop image processor failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
106         }
107     } else {
108         DHLOGI("%{public}s: Processor is null, Setup first.", DSCREEN_LOG_TAG);
109     }
110 
111     if (screenChannel_ != nullptr) {
112         StartTrace(DSCREEN_HITRACE_LABEL, DSCREEN_SINK_CLOSE_SESSION_START);
113         ret = screenChannel_->CloseSession();
114         FinishTrace(DSCREEN_HITRACE_LABEL);
115         if (ret != DH_SUCCESS) {
116             DHLOGW("%{public}s: Close Session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
117         }
118     } else {
119         DHLOGI("%{public}s: Channel is null, Setup first.", DSCREEN_LOG_TAG);
120     }
121 
122     DHLOGI("%{public}s: Stop success.", DSCREEN_LOG_TAG);
123     return DH_SUCCESS;
124 }
125 
RegisterStateCallback(const std::shared_ptr<IScreenSinkTransCallback> & callback)126 int32_t ScreenSinkTrans::RegisterStateCallback(const std::shared_ptr<IScreenSinkTransCallback> &callback)
127 {
128     DHLOGI("%{public}s:RegisterStateCallback.", DSCREEN_LOG_TAG);
129     if (callback == nullptr) {
130         DHLOGE("%{public}s: Trans callback is null.", DSCREEN_LOG_TAG);
131         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
132     }
133     transCallback_ = callback;
134 
135     return DH_SUCCESS;
136 }
137 
SetImageSurface(const sptr<Surface> & surface)138 int32_t ScreenSinkTrans::SetImageSurface(const sptr<Surface> &surface)
139 {
140     if (surface == nullptr) {
141         DHLOGE("%{public}s: Image surface is null.", DSCREEN_LOG_TAG);
142         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
143     }
144     decoderSurface_ = surface;
145 
146     return DH_SUCCESS;
147 }
148 
CheckVideoParam(const VideoParam & param)149 int32_t ScreenSinkTrans::CheckVideoParam(const VideoParam &param)
150 {
151     if ((param.GetCodecType() != VIDEO_CODEC_TYPE_VIDEO_H264) &&
152         (param.GetCodecType() != VIDEO_CODEC_TYPE_VIDEO_H265) &&
153         (param.GetCodecType() != VIDEO_CODEC_TYPE_VIDEO_MPEG4)) {
154         DHLOGE("%{public}s: Invalid codec type.", DSCREEN_LOG_TAG);
155         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
156     }
157 
158     if ((param.GetVideoFormat() != VIDEO_DATA_FORMAT_YUVI420) &&
159         (param.GetVideoFormat() != VIDEO_DATA_FORMAT_NV12) &&
160         (param.GetVideoFormat() != VIDEO_DATA_FORMAT_NV21) &&
161         (param.GetVideoFormat() != VIDEO_DATA_FORMAT_RGBA8888)) {
162         DHLOGE("%{public}s: Invalid video data format.", DSCREEN_LOG_TAG);
163         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
164     }
165 
166     if ((param.GetVideoWidth() > DSCREEN_MAX_VIDEO_DATA_WIDTH) ||
167         (param.GetVideoHeight() > DSCREEN_MAX_VIDEO_DATA_HEIGHT)) {
168         DHLOGE("%{public}s: Invalid video data size.", DSCREEN_LOG_TAG);
169         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
170     }
171 
172     if ((param.GetScreenWidth() > DSCREEN_MAX_SCREEN_DATA_WIDTH) ||
173         (param.GetScreenHeight() > DSCREEN_MAX_SCREEN_DATA_HEIGHT)) {
174         DHLOGE("%{public}s: Invalid screen data size.", DSCREEN_LOG_TAG);
175         return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
176     }
177 
178     return DH_SUCCESS;
179 }
180 
CheckTransParam(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)181 int32_t ScreenSinkTrans::CheckTransParam(const VideoParam &localParam, const VideoParam &remoteParam,
182     const std::string &peerDevId)
183 {
184     if (peerDevId.empty()) {
185         DHLOGE("%{public}s: Remote device id is null.", DSCREEN_LOG_TAG);
186         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
187     }
188 
189     int32_t ret = CheckVideoParam(localParam);
190     if (ret != DH_SUCCESS) {
191         DHLOGE("%{public}s: check localParam param failed.", DSCREEN_LOG_TAG);
192         return ret;
193     }
194 
195     ret = CheckVideoParam(remoteParam);
196     if (ret != DH_SUCCESS) {
197         DHLOGE("%{public}s: check remoteParam param failed.", DSCREEN_LOG_TAG);
198         return ret;
199     }
200     return DH_SUCCESS;
201 }
202 
InitScreenTrans(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)203 int32_t ScreenSinkTrans::InitScreenTrans(const VideoParam &localParam, const VideoParam &remoteParam,
204     const std::string &peerDevId)
205 {
206     screenChannel_ = std::make_shared<ScreenDataChannelImpl>(peerDevId);
207     if (std::atoi(version_.c_str()) > DSCREEN_MIN_VERSION) {
208         screenChannel_->SetJpegSessionFlag(true);
209     }
210     int32_t ret = RegisterChannelListener();
211     if (ret != DH_SUCCESS) {
212         DHLOGE("%{public}s: Register channel listener failed.", DSCREEN_LOG_TAG);
213         screenChannel_ = nullptr;
214         return ret;
215     }
216 
217     imageProcessor_ = std::make_shared<ImageSinkProcessor>();
218 
219     ret = RegisterProcessorListener(localParam, remoteParam, peerDevId);
220     if (ret != DH_SUCCESS) {
221         DHLOGE("%{public}s: Register processor listener failed.", DSCREEN_LOG_TAG);
222         screenChannel_ = nullptr;
223         imageProcessor_ = nullptr;
224         return ret;
225     }
226 
227     return DH_SUCCESS;
228 }
229 
RegisterChannelListener()230 int32_t ScreenSinkTrans::RegisterChannelListener()
231 {
232     DHLOGI("%{public}s: RegisterChannelListener.", DSCREEN_LOG_TAG);
233     std::shared_ptr<IScreenChannelListener> listener = shared_from_this();
234     if (listener == nullptr) {
235         DHLOGE("%{public}s: Channel Listener is null.", DSCREEN_LOG_TAG);
236         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
237     }
238 
239     int32_t ret = screenChannel_->CreateSession(listener);
240     if (ret != DH_SUCCESS) {
241         DHLOGE("%{public}s: Register channel listenner failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
242         ReportOptFail(DSCREEN_OPT_FAIL, ret, "dscreen sink Create session failed.");
243         return ret;
244     }
245 
246     return DH_SUCCESS;
247 }
248 
RegisterProcessorListener(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)249 int32_t ScreenSinkTrans::RegisterProcessorListener(const VideoParam &localParam, const VideoParam &remoteParam,
250     const std::string &peerDevId)
251 {
252     if (imageProcessor_ == nullptr || decoderSurface_ == nullptr) {
253         DHLOGE("%{public}s: imageProcessor_ or decoderSurface_ is nullptr.", DSCREEN_LOG_TAG);
254         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
255     }
256     DHLOGI("%{public}s: RegisterProcessorListener.", DSCREEN_LOG_TAG);
257     std::shared_ptr<IImageSinkProcessorListener> listener = shared_from_this();
258     if (listener == nullptr) {
259         DHLOGE("%{public}s: Channel listener to null.", DSCREEN_LOG_TAG);
260         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
261     }
262 
263     int32_t ret = imageProcessor_->ConfigureImageProcessor(localParam, remoteParam, listener);
264     if (ret != DH_SUCCESS) {
265         DHLOGE("%{public}s: Config image processor failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
266         ReportOptFail(DSCREEN_OPT_FAIL, ret, "Config image processor failed.");
267         return ret;
268     }
269 
270     ret = imageProcessor_->SetImageSurface(decoderSurface_);
271     if (ret != DH_SUCCESS) {
272         DHLOGE("%{public}s: Set image surface failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
273         return ret;
274     }
275     return DH_SUCCESS;
276 }
277 
OnSessionOpened()278 void ScreenSinkTrans::OnSessionOpened()
279 {
280     DHLOGI("%{public}s: OnChannelSessionOpened and start enable low latency", DSCREEN_LOG_TAG);
281     std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = DScreenFwkKit::GetInstance().GetDHFwkKit();
282     if (dhFwkKit != nullptr) {
283         int32_t ret = dhFwkKit->PublishMessage(DHTopic::TOPIC_LOW_LATENCY, ENABLE_LOW_LATENCY.dump());
284         if (ret != DH_FWK_SUCCESS) {
285             DHLOGE("%{public}s: Sink start enable low latency failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
286         }
287     }
288 }
289 
OnSessionClosed()290 void ScreenSinkTrans::OnSessionClosed()
291 {
292     DHLOGI("%{public}s: OnChannelSessionClosed and stop enable low latency", DSCREEN_LOG_TAG);
293     std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = DScreenFwkKit::GetInstance().GetDHFwkKit();
294     if (dhFwkKit != nullptr) {
295         int32_t ret = dhFwkKit->PublishMessage(DHTopic::TOPIC_LOW_LATENCY, DISABLE_LOW_LATENCY.dump());
296         if (ret != DH_FWK_SUCCESS) {
297             DHLOGE("%{public}s: Sink stop enable low latency failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
298         }
299     }
300 
301     std::shared_ptr<IScreenSinkTransCallback> callback = transCallback_.lock();
302     if (callback == nullptr) {
303         DHLOGE("%{public}s: Trans callback is null.", DSCREEN_LOG_TAG);
304         return;
305     }
306     callback->OnError(ERR_DH_SCREEN_TRANS_SESSION_CLOSED, "OnChannelSessionClosed");
307 }
308 
OnDataReceived(const std::shared_ptr<DataBuffer> & data)309 void ScreenSinkTrans::OnDataReceived(const std::shared_ptr<DataBuffer> &data)
310 {
311     if (imageProcessor_ == nullptr || data == nullptr) {
312         DHLOGE("%{public}s: imageProcessor_ or data is nullptr.", DSCREEN_LOG_TAG);
313         return;
314     }
315     DHLOGD("%{public}s: OnChannelDataReceived.", DSCREEN_LOG_TAG);
316     int32_t ret = imageProcessor_->ProcessImage(data);
317     if (ret != DH_SUCCESS) {
318         DHLOGE("%{public}s: send data to image processor failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
319     }
320 }
321 
SetScreenVersion(const std::string & version)322 void ScreenSinkTrans::SetScreenVersion(const std::string &version)
323 {
324     version_ = version;
325 }
326 
OnProcessorStateNotify(int32_t state)327 void ScreenSinkTrans::OnProcessorStateNotify(int32_t state)
328 {
329     DHLOGI("%{public}s: OnProcessorStateNotify.", DSCREEN_LOG_TAG);
330     std::shared_ptr<IScreenSinkTransCallback> callback = transCallback_.lock();
331     if (callback == nullptr) {
332         DHLOGE("%{public}s: Trans callback is null.", DSCREEN_LOG_TAG);
333         return;
334     }
335     callback->OnError(state, "OnProcessorStateNotify");
336 }
337 } // namespace DistributedHardware
338 } // namespace OHOS