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