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 return DH_SUCCESS;
199 }
200
InitScreenTrans(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)201 int32_t ScreenSinkTrans::InitScreenTrans(const VideoParam &localParam, const VideoParam &remoteParam,
202 const std::string &peerDevId)
203 {
204 screenChannel_ = std::make_shared<ScreenDataChannelImpl>(peerDevId);
205 if (std::atoi(version_.c_str()) > DSCREEN_MIN_VERSION) {
206 screenChannel_->SetJpegSessionFlag(true);
207 }
208 int32_t ret = RegisterChannelListener();
209 if (ret != DH_SUCCESS) {
210 DHLOGE("%s: Register channel listener failed.", LOG_TAG);
211 screenChannel_ = nullptr;
212 return ret;
213 }
214
215 imageProcessor_ = std::make_shared<ImageSinkProcessor>();
216
217 ret = RegisterProcessorListener(localParam, remoteParam, peerDevId);
218 if (ret != DH_SUCCESS) {
219 DHLOGE("%s: Register processor listener failed.", LOG_TAG);
220 screenChannel_ = nullptr;
221 imageProcessor_ = nullptr;
222 return ret;
223 }
224
225 return DH_SUCCESS;
226 }
227
RegisterChannelListener()228 int32_t ScreenSinkTrans::RegisterChannelListener()
229 {
230 DHLOGI("%s: RegisterChannelListener.", LOG_TAG);
231 std::shared_ptr<IScreenChannelListener> listener = shared_from_this();
232 if (listener == nullptr) {
233 DHLOGE("%s: Channel Listener is null.", LOG_TAG);
234 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
235 }
236
237 int32_t ret = screenChannel_->CreateSession(listener);
238 if (ret != DH_SUCCESS) {
239 DHLOGE("%s: Register channel listenner failed ret: %" PRId32, LOG_TAG, ret);
240 ReportOptFail(DSCREEN_OPT_FAIL, ret, "dscreen sink Create session failed.");
241 return ret;
242 }
243
244 return DH_SUCCESS;
245 }
246
RegisterProcessorListener(const VideoParam & localParam,const VideoParam & remoteParam,const std::string & peerDevId)247 int32_t ScreenSinkTrans::RegisterProcessorListener(const VideoParam &localParam, const VideoParam &remoteParam,
248 const std::string &peerDevId)
249 {
250 if (imageProcessor_ == nullptr || decoderSurface_ == nullptr) {
251 DHLOGE("%s: imageProcessor_ or decoderSurface_ is nullptr.", LOG_TAG);
252 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
253 }
254 DHLOGI("%s: RegisterProcessorListener.", LOG_TAG);
255 std::shared_ptr<IImageSinkProcessorListener> listener = shared_from_this();
256 if (listener == nullptr) {
257 DHLOGE("%s: Channel listener to null.", LOG_TAG);
258 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
259 }
260
261 int32_t ret = imageProcessor_->ConfigureImageProcessor(localParam, remoteParam, listener);
262 if (ret != DH_SUCCESS) {
263 DHLOGE("%s: Config image processor failed ret: %" PRId32, LOG_TAG, ret);
264 ReportOptFail(DSCREEN_OPT_FAIL, ret, "Config image processor failed.");
265 return ret;
266 }
267
268 ret = imageProcessor_->SetImageSurface(decoderSurface_);
269 if (ret != DH_SUCCESS) {
270 DHLOGE("%s: Set image surface failed ret: %" PRId32, LOG_TAG, ret);
271 return ret;
272 }
273 return DH_SUCCESS;
274 }
275
OnSessionOpened()276 void ScreenSinkTrans::OnSessionOpened()
277 {
278 DHLOGI("%s: OnChannelSessionOpened and start enable low latency", LOG_TAG);
279 std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = DScreenFwkKit::GetInstance().GetDHFwkKit();
280 if (dhFwkKit != nullptr) {
281 int32_t ret = dhFwkKit->PublishMessage(DHTopic::TOPIC_LOW_LATENCY, ENABLE_LOW_LATENCY.dump());
282 if (ret != DH_FWK_SUCCESS) {
283 DHLOGE("%s: Sink start enable low latency failed ret: %." PRId32, LOG_TAG, ret);
284 }
285 }
286 }
287
OnSessionClosed()288 void ScreenSinkTrans::OnSessionClosed()
289 {
290 DHLOGI("%s: OnChannelSessionClosed and stop enable low latency", LOG_TAG);
291 std::shared_ptr<DistributedHardwareFwkKit> dhFwkKit = DScreenFwkKit::GetInstance().GetDHFwkKit();
292 if (dhFwkKit != nullptr) {
293 int32_t ret = dhFwkKit->PublishMessage(DHTopic::TOPIC_LOW_LATENCY, DISABLE_LOW_LATENCY.dump());
294 if (ret != DH_FWK_SUCCESS) {
295 DHLOGE("%s: Sink stop enable low latency failed ret: %." PRId32, LOG_TAG, ret);
296 }
297 }
298
299 std::shared_ptr<IScreenSinkTransCallback> callback = transCallback_.lock();
300 if (callback == nullptr) {
301 DHLOGE("%s: Trans callback is null.", LOG_TAG);
302 return;
303 }
304 callback->OnError(ERR_DH_SCREEN_TRANS_SESSION_CLOSED, "OnChannelSessionClosed");
305 }
306
OnDataReceived(const std::shared_ptr<DataBuffer> & data)307 void ScreenSinkTrans::OnDataReceived(const std::shared_ptr<DataBuffer> &data)
308 {
309 if (imageProcessor_ == nullptr || data == nullptr) {
310 DHLOGE("%s: imageProcessor_ or data is nullptr.", LOG_TAG);
311 return;
312 }
313 DHLOGD("%s: OnChannelDataReceived.", LOG_TAG);
314 int32_t ret = imageProcessor_->ProcessImage(data);
315 if (ret != DH_SUCCESS) {
316 DHLOGE("%s: send data to image processor failed ret: %" PRId32, LOG_TAG, ret);
317 }
318 }
319
SetScreenVersion(const std::string & version)320 void ScreenSinkTrans::SetScreenVersion(const std::string &version)
321 {
322 version_ = version;
323 }
324
OnProcessorStateNotify(int32_t state)325 void ScreenSinkTrans::OnProcessorStateNotify(int32_t state)
326 {
327 DHLOGI("%s: OnProcessorStateNotify.", LOG_TAG);
328 std::shared_ptr<IScreenSinkTransCallback> callback = transCallback_.lock();
329 if (callback == nullptr) {
330 DHLOGE("%s: Trans callback is null.", LOG_TAG);
331 return;
332 }
333 callback->OnError(state, "OnProcessorStateNotify");
334 }
335 } // namespace DistributedHardware
336 } // namespace OHOS