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