1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "wfd_sink_demo.h"
17 #include <cstdint>
18 #include <iostream>
19 #include <memory>
20 #include <string>
21 #include <vector>
22 #include "common/sharing_log.h"
23 #include "extend/magic_enum/magic_enum.hpp"
24 #include "impl/scene/wfd/wfd_def.h"
25 #include "interaction/interprocess/client_factory.h"
26 #include "surface_utils.h"
27 #include "utils/utils.h"
28 #include "windowmgr/include/window_manager.h"
29
30 using namespace OHOS::Sharing;
31
32 VideoFormat DEFAULT_VIDEO_FORMAT = VideoFormat::VIDEO_1920X1080_30;
33 AudioFormat DEFAULT_AUDIO_FORMAT = AudioFormat::AUDIO_48000_16_2;
34 std::vector<std::pair<int32_t, int32_t>> position{{0, 0}, {960, 0}, {0, 540}, {960, 540}};
35
36 constexpr uint32_t DEFAULT_WIDTH = 1280;
37 constexpr uint32_t DEFAULT_HEIGHT = 720;
38
WfdSinkDemo()39 WfdSinkDemo::WfdSinkDemo()
40 {
41 listener_ = std::make_shared<WfdSinkDemoListener>();
42 if (!listener_)
43 printf("create WfdSinkDemoListener failed");
44 }
45
GetClient()46 std::shared_ptr<WfdSink> WfdSinkDemo::GetClient()
47 {
48 return client_;
49 }
50
CreateClient()51 bool WfdSinkDemo::CreateClient()
52 {
53 client_ = WfdSinkFactory::CreateSink(0, "wfd_sink_demo");
54 if (!client_) {
55 printf("create wfdsink client error");
56 return false;
57 }
58 if (listener_) {
59 listener_->SetListener(shared_from_this());
60 client_->SetListener(listener_);
61 return true;
62 } else {
63 printf("Listener is nullptr");
64 return false;
65 }
66 }
67
SetDiscoverable(bool enable)68 bool WfdSinkDemo::SetDiscoverable(bool enable)
69 {
70 if (client_) {
71 int ret = 0;
72 if (enable) {
73 ret = client_->Start();
74 } else {
75 ret = client_->Stop();
76 }
77 if (ret == 0) {
78 printf("start or stop p2p success");
79 return true;
80 }
81 }
82 printf("start or stop failed");
83 return false;
84 }
85
GetConfig()86 bool WfdSinkDemo::GetConfig()
87 {
88 return true;
89 }
90
Start()91 bool WfdSinkDemo::Start()
92 {
93 printf("enter start");
94 if (!client_) {
95 printf("client is nullptr");
96 return false;
97 }
98 if (client_->Start() == -1) {
99 printf("sink start error");
100 return false;
101 }
102 return true;
103 }
104
Stop()105 bool WfdSinkDemo::Stop()
106 {
107 printf("enter stop");
108 if (!client_) {
109 printf("client is nullptr");
110 return false;
111 }
112 if (client_->Stop() == -1) {
113 printf("sink stop error");
114 return false;
115 }
116 return true;
117 }
118
AppendSurface(std::string deviceId)119 bool WfdSinkDemo::AppendSurface(std::string deviceId)
120 {
121 if (!client_) {
122 printf("client is nullptr");
123 return false;
124 }
125 uint64_t surfaceId = 0;
126 for (auto item : surfaceUsing_) {
127 if (!item.second) {
128 surfaceId = item.first;
129 surfaceUsing_[surfaceId] = true;
130 }
131 }
132 if (surfaceId == 0 && wdnum_ < 4) {
133 // window1
134 printf("create window enter");
135 WindowProperty::Ptr windowPropertyPtr = std::make_shared<WindowProperty>();
136 windowPropertyPtr->height = DEFAULT_HEIGHT;
137 windowPropertyPtr->width = DEFAULT_WIDTH;
138 windowPropertyPtr->startX = position[wdnum_].first;
139 windowPropertyPtr->startY = position[wdnum_].second;
140 windowPropertyPtr->isFull = false;
141 windowPropertyPtr->isShow = true;
142 ++wdnum_;
143 int32_t windowId = WindowManager::GetInstance().CreateWindow(windowPropertyPtr);
144 sptr<Surface> surface = WindowManager::GetInstance().GetSurface(windowId);
145 surfaceId = surface->GetUniqueId();
146 int ret = SurfaceUtils::GetInstance()->Add(surfaceId, surface);
147 if (ret != 0)
148 printf("add failed");
149 surfaceUsing_.emplace(surfaceId, true);
150 surfaces_.push_back(surface);
151 }
152 printf("surfaceId: %llu", surfaceId);
153 if (client_->AppendSurface(deviceId, surfaceId) == -1) {
154 printf("SetSurface error");
155 return false;
156 }
157 surfaceDevMap_[surfaceId] = deviceId;
158 return true;
159 }
160
RemoveSurface(std::string deviceId,std::string surfaceId)161 bool WfdSinkDemo::RemoveSurface(std::string deviceId, std::string surfaceId)
162 {
163 if (!client_) {
164 printf("client is nullptr");
165 return false;
166 }
167 uint64_t surfaceUintId = std::stoull(surfaceId);
168 if (client_->RemoveSurface(deviceId, surfaceUintId) != 0) {
169 printf("delete surface:%llu failed", surfaceUintId);
170 return false;
171 }
172 return true;
173 }
174
SetMediaFormat(std::string deviceId,VideoFormat videoFormatId,AudioFormat audioFormatId)175 bool WfdSinkDemo::SetMediaFormat(std::string deviceId, VideoFormat videoFormatId, AudioFormat audioFormatId)
176 {
177 if (!client_) {
178 printf("client is nullptr");
179 return false;
180 }
181 CodecAttr videoAttr;
182 videoAttr.codecType = CodecId::CODEC_H264;
183 videoAttr.formatId = videoFormatId;
184 CodecAttr audioAttr;
185 audioAttr.codecType = CodecId::CODEC_AAC;
186 audioAttr.formatId = audioFormatId;
187
188 if (client_->SetMediaFormat(deviceId, videoAttr, audioAttr) == -1) {
189 printf("SetVideoFormat error, surfaceId: %s", deviceId.c_str());
190 return false;
191 }
192 return true;
193 }
194
SetSceneType(std::string deviceId,std::string surfaceId,SceneType sceneType)195 bool WfdSinkDemo::SetSceneType(std::string deviceId, std::string surfaceId, SceneType sceneType)
196 {
197 if (!client_) {
198 printf("client is nullptr");
199 return false;
200 }
201 uint64_t stringUintId = std::stoull(surfaceId);
202 if (client_->SetSceneType(deviceId, stringUintId, sceneType) == -1) {
203 printf("SetSceneType error, surfaceId: %s", deviceId.c_str());
204 return false;
205 }
206 return true;
207 }
208
Mute(std::string deviceId)209 bool WfdSinkDemo::Mute(std::string deviceId)
210 {
211 if (!client_) {
212 printf("client is nullptr");
213 return false;
214 }
215 if (client_->Mute(deviceId) == -1) {
216 printf("Mute error, deviceId: %s", deviceId.c_str());
217 return false;
218 }
219 return true;
220 }
221
UnMute(std::string deviceId)222 int32_t WfdSinkDemo::UnMute(std::string deviceId)
223 {
224 if (!client_) {
225 printf("client is nullptr");
226 return false;
227 }
228 if (client_->UnMute(deviceId) == -1) {
229 printf("UnMute error, deviceId: %s", deviceId.c_str());
230 return false;
231 }
232 return true;
233 }
234
AddDevice(const std::string deviceId)235 void WfdSinkDemo::AddDevice(const std::string deviceId)
236 {
237 devices_.push_back(deviceId);
238 }
239
RemoveDevice(const std::string deviceId)240 void WfdSinkDemo::RemoveDevice(const std::string deviceId)
241 {
242 printf("remove device: %s", deviceId.c_str());
243 for (uint32_t i = 0; i < devices_.size(); i++)
244 if (devices_[i] == deviceId) {
245 devices_.erase(devices_.begin() + i);
246 }
247 for (auto item : surfaceDevMap_) {
248 if (item.second == deviceId) {
249 printf("free surfacId: %llu", item.first);
250 surfaceUsing_[item.first] = false;
251 }
252 }
253 }
254
ListDevices()255 void WfdSinkDemo::ListDevices()
256 {
257 printf("The connected devices:");
258 for (auto str : devices_) {
259 printf("device : %s", str.c_str());
260 }
261 }
262
Play(std::string deviceId)263 bool WfdSinkDemo::Play(std::string deviceId)
264 {
265 if (!client_) {
266 printf("client is nullptr");
267 return false;
268 }
269 if (client_->Play(deviceId) == -1) {
270 printf("play error, deviceId: %s", deviceId.c_str());
271 return false;
272 }
273 return true;
274 }
275
Pause(std::string deviceId)276 bool WfdSinkDemo::Pause(std::string deviceId)
277 {
278 if (!client_) {
279 printf("client is nullptr");
280 return false;
281 }
282 if (client_->Pause(deviceId) == -1) {
283 printf("Pause error, deviceId: %s", deviceId.c_str());
284 return false;
285 }
286 return true;
287 }
288
Close(std::string deviceId)289 bool WfdSinkDemo::Close(std::string deviceId)
290 {
291 if (!client_) {
292 printf("client is nullptr");
293 return false;
294 }
295 RemoveDevice(deviceId);
296 if (client_->Close(deviceId) == -1) {
297 printf("close error, deviceId: %s", deviceId.c_str());
298 return false;
299 }
300 return true;
301 }
302
DoCmd(std::string cmd)303 void WfdSinkDemo::DoCmd(std::string cmd)
304 {
305 const std::map<std::string, int> cmd2index = {
306 {"GetConfig", 1}, {"Start", 2}, {"Stop", 3}, {"SetMediaFormat", 4}, {"Play", 5},
307 {"Pause", 6}, {"Close", 7}, {"Mute", 8}, {"UnMute", 9}, {"SetSceneType", 10},
308 {"ListDevice", 11}, {"AppendSurface", 12}, {"RemoveSurface", 13}};
309
310 if (cmd2index.count(cmd) == 0) {
311 printf("command: %s not found", cmd.c_str());
312 return;
313 }
314 printf("enter commond, the commond is %s, the id is %d", cmd.c_str(), cmd2index.at(cmd));
315 std::string input;
316 std::string deviceId;
317 std::string surfaceId;
318 VideoFormat videoFormatId = VIDEO_1920X1080_30;
319 AudioFormat audioFormatId = AUDIO_48000_16_2;
320 SceneType sceneType = FOREGROUND;
321 // input params
322 switch (cmd2index.at(cmd)) {
323 case 5: // play
324 case 6: // pause
325 case 7: // close
326 case 8: // mute
327 case 9: // unmute
328 case 12: // AppendSurface
329 printf("please input deviceId:");
330 getline(std::cin, input);
331 if (input != "") {
332 deviceId = input;
333 }
334 break;
335 case 10: // SetSceneType
336 printf("please input deviceId:");
337 getline(std::cin, input);
338 if (input != "") {
339 deviceId = input;
340 }
341 printf("please input surfaceId:");
342 getline(std::cin, input);
343 if (input != "") {
344 surfaceId = input;
345 }
346 printf("please input scenetype: default for 0, (0: FOREGROUND, 1: BACKGROUND)");
347 getline(std::cin, input);
348 if (input != "") {
349 sceneType = static_cast<SceneType>(atoi(input.c_str()));
350 }
351 break;
352 case 4: // SetMediaFormat
353 printf("please input deviceId:");
354 getline(std::cin, input);
355 if (input != "") {
356 deviceId = input;
357 }
358 getline(std::cin, input);
359 if (input != "") {
360 videoFormatId = static_cast<VideoFormat>(atoi(input.c_str()));
361 }
362 getline(std::cin, input);
363 if (input != "") {
364 audioFormatId = static_cast<AudioFormat>(atoi(input.c_str()));
365 }
366 break;
367 case 13: // delsurface
368 printf("please input deviceId:");
369 getline(std::cin, input);
370 if (input != "") {
371 deviceId = input;
372 }
373 printf("please input surfaceId:");
374 getline(std::cin, input);
375 if (input != "") {
376 surfaceId = input;
377 }
378 break;
379 default:
380 break;
381 }
382 // execute command
383 switch (cmd2index.at(cmd)) {
384 case 1: // GetConfig
385 if (GetConfig()) {
386 printf("GetConfig success");
387 }
388 break;
389 case 2: // start
390 if (Start()) {
391 printf("p2p start success");
392 }
393 break;
394 case 3: // Stop
395 if (Stop()) {
396 printf("p2p stop success");
397 }
398 break;
399 case 4: // SetMediaFormat
400 if (SetMediaFormat(deviceId, videoFormatId, audioFormatId)) {
401 printf("Start success");
402 }
403 break;
404 case 5: // Play
405 if (Play(deviceId)) {
406 printf("Play success");
407 }
408 break;
409 case 6: // Close
410 if (Pause(deviceId)) {
411 printf("Pause success");
412 }
413 break;
414 case 7: // Close
415 if (Close(deviceId)) {
416 printf("Close success");
417 }
418 break;
419 case 8: // Mute
420 if (Mute(deviceId)) {
421 printf("Mute success");
422 }
423 break;
424 case 9: // UnMute
425 if (UnMute(deviceId)) {
426 printf("UnMute success");
427 }
428 break;
429 case 10: // SetSceneType
430 if (SetSceneType(deviceId, surfaceId, sceneType)) {
431 printf("UnMute success");
432 }
433 break;
434 case 11: // ListDevice
435 ListDevices();
436 break;
437 case 12:
438 AppendSurface(deviceId);
439 break;
440 case 13:
441 RemoveSurface(deviceId, surfaceId);
442 break;
443 default:
444 break;
445 }
446 }
447
OnError(uint32_t regionId,uint32_t agentId,SharingErrorCode errorCode)448 void WfdSinkDemoListener::OnError(uint32_t regionId, uint32_t agentId, SharingErrorCode errorCode)
449 {
450 printf("on error. errorCode: %s, %d", std::string(magic_enum::enum_name(errorCode)).c_str(), errorCode);
451 }
452
OnInfo(std::shared_ptr<BaseMsg> & msg)453 void WfdSinkDemoListener::OnInfo(std::shared_ptr<BaseMsg> &msg)
454 {
455 printf("on Info. msgId: %d", msg->GetMsgId());
456 switch (msg->GetMsgId()) {
457 case WfdConnectionChangedMsg::MSG_ID: {
458 auto data = std::static_pointer_cast<WfdConnectionChangedMsg>(msg);
459 ConnectionInfo info;
460 info.ip = data->ip;
461 info.mac = data->mac;
462 info.state = static_cast<ConnectionState>(data->state);
463 info.surfaceId = data->surfaceId;
464 info.deviceName = data->deviceName;
465 info.primaryDeviceType = data->primaryDeviceType;
466 info.secondaryDeviceType = data->secondaryDeviceType;
467 OnConnectionChanged(info);
468 break;
469 }
470 default:
471 break;
472 }
473 }
474
OnConnectionChanged(const ConnectionInfo & info)475 void WfdSinkDemoListener::OnConnectionChanged(const ConnectionInfo &info)
476 {
477 auto listener = listener_.lock();
478 if (!listener) {
479 printf("no listener");
480 return;
481 }
482 switch (info.state) {
483 case ConnectionState::CONNECTED: {
484 listener->AddDevice(info.mac);
485 listener->AppendSurface(info.mac);
486 listener->SetMediaFormat(info.mac, DEFAULT_VIDEO_FORMAT, DEFAULT_AUDIO_FORMAT);
487 listener->Play(info.mac);
488 break;
489 }
490 case ConnectionState::DISCONNECTED: {
491 listener->RemoveDevice(info.mac);
492 break;
493 }
494 default:
495 break;
496 }
497 printf("on OnConnectionChanged. ip: %s, mac: %s, surfaceId: %llu", info.ip.c_str(), info.mac.c_str(),
498 info.surfaceId);
499 }
500
TestOneByOne()501 int TestOneByOne()
502 {
503 printf("ENTER TEST");
504 std::map<std::string, std::string> cmdMap = {
505 {"1", "GetConfig"}, {"2", "AppendSurface"}, {"3", "SetMediaFormat"}, {"4", "Start"},
506 {"5", "Stop"}, {"6", "ListDevice"}, {"7", "Play"}, {"8", "Pause"},
507 {"9", "Close"}, {"10", "SetSceneType"}, {"11", "Mute"}, {"12", "UnMute"}};
508
509 std::string helpNotice = "select steps: 0-quit;"
510 "1-GetConfig; 2-AppendSurface;"
511 "3-SetMediaFormat; 4-Start;"
512 "5-Stop; 6-ListDevice;"
513 "7-Play; 8-Pause;"
514 "9-Close; 10-SetSceneType;"
515 "11-Mute; 12-UnMute";
516
517 std::shared_ptr<WfdSinkDemo> demo = std::make_shared<WfdSinkDemo>();
518 if (!demo->CreateClient()) {
519 printf("create client failed");
520 return -1;
521 }
522 std::string inputCmd;
523 while (1) {
524 printf("%s", helpNotice.c_str());
525 getline(std::cin, inputCmd);
526 if (inputCmd == "") {
527 continue;
528 } else if (inputCmd == "0") {
529 break;
530 } else {
531 if (cmdMap.count(inputCmd) == 0) {
532 printf("no cmd: %s, input again", inputCmd.c_str());
533 continue;
534 } else {
535 demo->DoCmd(cmdMap[inputCmd]);
536 }
537 }
538 }
539
540 return 0;
541 }
542
main()543 int main()
544 {
545 printf("wfd sink test start!");
546 TestOneByOne();
547 return 0;
548 }