• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param)
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