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 if (client_->Stop() == -1) {
108 printf("sink stop error");
109 return false;
110 }
111 return true;
112 }
113
AppendSurface(std::string deviceId)114 bool WfdSinkDemo::AppendSurface(std::string deviceId)
115 {
116 uint64_t surfaceId = 0;
117 for (auto item : surfaceUsing_) {
118 if (!item.second) {
119 surfaceId = item.first;
120 surfaceUsing_[surfaceId] = true;
121 }
122 }
123 if (surfaceId == 0 && wdnum_ < 4) {
124 // window1
125 printf("create window enter");
126 WindowProperty::Ptr windowPropertyPtr = std::make_shared<WindowProperty>();
127 windowPropertyPtr->height = DEFAULT_HEIGHT;
128 windowPropertyPtr->width = DEFAULT_WIDTH;
129 windowPropertyPtr->startX = position[wdnum_].first;
130 windowPropertyPtr->startY = position[wdnum_].second;
131 windowPropertyPtr->isFull = false;
132 windowPropertyPtr->isShow = true;
133 ++wdnum_;
134 int32_t windowId = WindowManager::GetInstance().CreateWindow(windowPropertyPtr);
135 sptr<Surface> surface = WindowManager::GetInstance().GetSurface(windowId);
136 surfaceId = surface->GetUniqueId();
137 int ret = SurfaceUtils::GetInstance()->Add(surfaceId, surface);
138 if (ret != 0)
139 printf("add failed");
140 surfaceUsing_.emplace(surfaceId, true);
141 surfaces_.push_back(surface);
142 }
143 printf("surfaceId: %llu", surfaceId);
144 if (client_->AppendSurface(deviceId, surfaceId) == -1) {
145 printf("SetSurface error");
146 return false;
147 }
148 surfaceDevMap_[surfaceId] = deviceId;
149 return true;
150 }
151
RemoveSurface(std::string deviceId,std::string surfaceId)152 bool WfdSinkDemo::RemoveSurface(std::string deviceId, std::string surfaceId)
153 {
154 uint64_t surfaceUintId = std::stoull(surfaceId);
155 if (client_->RemoveSurface(deviceId, surfaceUintId) != 0) {
156 printf("delete surface:%llu failed", surfaceUintId);
157 return false;
158 }
159 return true;
160 }
161
SetMediaFormat(std::string deviceId,VideoFormat videoFormatId,AudioFormat audioFormatId)162 bool WfdSinkDemo::SetMediaFormat(std::string deviceId, VideoFormat videoFormatId, AudioFormat audioFormatId)
163 {
164 CodecAttr videoAttr;
165 videoAttr.codecType = CodecId::CODEC_H264;
166 videoAttr.formatId = videoFormatId;
167 CodecAttr audioAttr;
168 audioAttr.codecType = CodecId::CODEC_AAC;
169 audioAttr.formatId = audioFormatId;
170
171 if (client_->SetMediaFormat(deviceId, videoAttr, audioAttr) == -1) {
172 printf("SetVideoFormat error, surfaceId: %s", deviceId.c_str());
173 return false;
174 }
175 return true;
176 }
177
SetSceneType(std::string deviceId,std::string surfaceId,SceneType sceneType)178 bool WfdSinkDemo::SetSceneType(std::string deviceId, std::string surfaceId, SceneType sceneType)
179 {
180 uint64_t stringUintId = std::stoull(surfaceId);
181 if (client_->SetSceneType(deviceId, stringUintId, sceneType) == -1) {
182 printf("SetSceneType error, surfaceId: %s", deviceId.c_str());
183 return false;
184 }
185 return true;
186 }
187
Mute(std::string deviceId)188 bool WfdSinkDemo::Mute(std::string deviceId)
189 {
190 if (client_->Mute(deviceId) == -1) {
191 printf("Mute error, deviceId: %s", deviceId.c_str());
192 return false;
193 }
194 return true;
195 }
196
UnMute(std::string deviceId)197 int32_t WfdSinkDemo::UnMute(std::string deviceId)
198 {
199 if (client_->UnMute(deviceId) == -1) {
200 printf("UnMute error, deviceId: %s", deviceId.c_str());
201 return false;
202 }
203 return true;
204 }
205
AddDevice(const std::string deviceId)206 void WfdSinkDemo::AddDevice(const std::string deviceId)
207 {
208 devices_.push_back(deviceId);
209 }
210
RemoveDevice(const std::string deviceId)211 void WfdSinkDemo::RemoveDevice(const std::string deviceId)
212 {
213 printf("remove device: %s", deviceId.c_str());
214 for (uint32_t i = 0; i < devices_.size(); i++)
215 if (devices_[i] == deviceId) {
216 devices_.erase(devices_.begin() + i);
217 }
218 for (auto item : surfaceDevMap_) {
219 if (item.second == deviceId) {
220 printf("free surfacId: %llu", item.first);
221 surfaceUsing_[item.first] = false;
222 }
223 }
224 }
225
ListDevices()226 void WfdSinkDemo::ListDevices()
227 {
228 printf("The connected devices:");
229 for (auto str : devices_) {
230 printf("device : %s", str.c_str());
231 }
232 }
233
Play(std::string deviceId)234 bool WfdSinkDemo::Play(std::string deviceId)
235 {
236 if (client_->Play(deviceId) == -1) {
237 printf("play error, deviceId: %s", deviceId.c_str());
238 return false;
239 }
240 return true;
241 }
242
Pause(std::string deviceId)243 bool WfdSinkDemo::Pause(std::string deviceId)
244 {
245 if (client_->Pause(deviceId) == -1) {
246 printf("Pause error, deviceId: %s", deviceId.c_str());
247 return false;
248 }
249 return true;
250 }
251
Close(std::string deviceId)252 bool WfdSinkDemo::Close(std::string deviceId)
253 {
254 RemoveDevice(deviceId);
255 if (client_->Close(deviceId) == -1) {
256 printf("close error, deviceId: %s", deviceId.c_str());
257 return false;
258 }
259 return true;
260 }
261
DoCmd(std::string cmd)262 void WfdSinkDemo::DoCmd(std::string cmd)
263 {
264 const std::map<std::string, int> cmd2index = {
265 {"GetConfig", 1}, {"Start", 2}, {"Stop", 3}, {"SetMediaFormat", 4}, {"Play", 5},
266 {"Pause", 6}, {"Close", 7}, {"Mute", 8}, {"UnMute", 9}, {"SetSceneType", 10},
267 {"ListDevice", 11}, {"AppendSurface", 12}, {"RemoveSurface", 13}};
268
269 if (cmd2index.count(cmd) == 0) {
270 printf("command: %s not found", cmd.c_str());
271 return;
272 }
273 printf("enter commond, the commond is %s, the id is %d", cmd.c_str(), cmd2index.at(cmd));
274 std::string input;
275 std::string deviceId;
276 std::string surfaceId;
277 VideoFormat videoFormatId = VIDEO_1920X1080_30;
278 AudioFormat audioFormatId = AUDIO_48000_16_2;
279 SceneType sceneType = FOREGROUND;
280 // input params
281 switch (cmd2index.at(cmd)) {
282 case 5: // play
283 case 6: // pause
284 case 7: // close
285 case 8: // mute
286 case 9: // unmute
287 case 12: // AppendSurface
288 printf("please input deviceId:");
289 getline(std::cin, input);
290 if (input != "") {
291 deviceId = input;
292 }
293 break;
294 case 10: // SetSceneType
295 printf("please input deviceId:");
296 getline(std::cin, input);
297 if (input != "") {
298 deviceId = input;
299 }
300 printf("please input surfaceId:");
301 getline(std::cin, input);
302 if (input != "") {
303 surfaceId = input;
304 }
305 printf("please input scenetype: default for 0, (0: FOREGROUND, 1: BACKGROUND)");
306 getline(std::cin, input);
307 if (input != "") {
308 sceneType = static_cast<SceneType>(atoi(input.c_str()));
309 }
310 break;
311 case 4: // SetMediaFormat
312 printf("please input deviceId:");
313 getline(std::cin, input);
314 if (input != "") {
315 deviceId = input;
316 }
317 getline(std::cin, input);
318 if (input != "") {
319 videoFormatId = static_cast<VideoFormat>(atoi(input.c_str()));
320 }
321 getline(std::cin, input);
322 if (input != "") {
323 audioFormatId = static_cast<AudioFormat>(atoi(input.c_str()));
324 }
325 break;
326 case 13: // delsurface
327 printf("please input deviceId:");
328 getline(std::cin, input);
329 if (input != "") {
330 deviceId = input;
331 }
332 printf("please input surfaceId:");
333 getline(std::cin, input);
334 if (input != "") {
335 surfaceId = input;
336 }
337 break;
338 default:
339 break;
340 }
341 // execute command
342 switch (cmd2index.at(cmd)) {
343 case 1: // GetConfig
344 if (GetConfig()) {
345 printf("GetConfig success");
346 }
347 break;
348 case 2: // start
349 if (Start()) {
350 printf("p2p start success");
351 }
352 break;
353 case 3: // Stop
354 if (Stop()) {
355 printf("p2p stop success");
356 }
357 break;
358 case 4: // SetMediaFormat
359 if (SetMediaFormat(deviceId, videoFormatId, audioFormatId)) {
360 printf("Start success");
361 }
362 break;
363 case 5: // Play
364 if (Play(deviceId)) {
365 printf("Play success");
366 }
367 break;
368 case 6: // Close
369 if (Pause(deviceId)) {
370 printf("Pause success");
371 }
372 break;
373 case 7: // Close
374 if (Close(deviceId)) {
375 printf("Close success");
376 }
377 break;
378 case 8: // Mute
379 if (Mute(deviceId)) {
380 printf("Mute success");
381 }
382 break;
383 case 9: // UnMute
384 if (UnMute(deviceId)) {
385 printf("UnMute success");
386 }
387 break;
388 case 10: // SetSceneType
389 if (SetSceneType(deviceId, surfaceId, sceneType)) {
390 printf("UnMute success");
391 }
392 break;
393 case 11: // ListDevice
394 ListDevices();
395 break;
396 case 12:
397 AppendSurface(deviceId);
398 break;
399 case 13:
400 RemoveSurface(deviceId, surfaceId);
401 break;
402 default:
403 break;
404 }
405 }
406
OnError(uint32_t regionId,uint32_t agentId,SharingErrorCode errorCode)407 void WfdSinkDemoListener::OnError(uint32_t regionId, uint32_t agentId, SharingErrorCode errorCode)
408 {
409 printf("on error. errorCode: %s, %d", std::string(magic_enum::enum_name(errorCode)).c_str(), errorCode);
410 }
411
OnInfo(std::shared_ptr<BaseMsg> & msg)412 void WfdSinkDemoListener::OnInfo(std::shared_ptr<BaseMsg> &msg)
413 {
414 printf("on Info. msgId: %d", msg->GetMsgId());
415 switch (msg->GetMsgId()) {
416 case WfdConnectionChangedMsg::MSG_ID: {
417 auto data = std::static_pointer_cast<WfdConnectionChangedMsg>(msg);
418 ConnectionInfo info;
419 info.ip = data->ip;
420 info.mac = data->mac;
421 info.state = static_cast<ConnectionState>(data->state);
422 info.surfaceId = data->surfaceId;
423 info.deviceName = data->deviceName;
424 info.primaryDeviceType = data->primaryDeviceType;
425 info.secondaryDeviceType = data->secondaryDeviceType;
426 OnConnectionChanged(info);
427 break;
428 }
429 default:
430 break;
431 }
432 }
433
OnConnectionChanged(const ConnectionInfo & info)434 void WfdSinkDemoListener::OnConnectionChanged(const ConnectionInfo &info)
435 {
436 auto listener = listener_.lock();
437 if (!listener) {
438 printf("no listener");
439 }
440 switch (info.state) {
441 case ConnectionState::CONNECTED: {
442 listener->AddDevice(info.mac);
443 listener->AppendSurface(info.mac);
444 listener->SetMediaFormat(info.mac, DEFAULT_VIDEO_FORMAT, DEFAULT_AUDIO_FORMAT);
445 listener->Play(info.mac);
446 break;
447 }
448 case ConnectionState::DISCONNECTED: {
449 listener->RemoveDevice(info.mac);
450 break;
451 }
452 default:
453 break;
454 }
455 printf("on OnConnectionChanged. ip: %s, mac: %s, surfaceId: %llu", info.ip.c_str(), info.mac.c_str(),
456 info.surfaceId);
457 }
458
TestOneByOne()459 int TestOneByOne()
460 {
461 printf("ENTER TEST");
462 std::map<std::string, std::string> cmdMap = {
463 {"1", "GetConfig"}, {"2", "AppendSurface"}, {"3", "SetMediaFormat"}, {"4", "Start"},
464 {"5", "Stop"}, {"6", "ListDevice"}, {"7", "Play"}, {"8", "Pause"},
465 {"9", "Close"}, {"10", "SetSceneType"}, {"11", "Mute"}, {"12", "UnMute"}};
466
467 std::string helpNotice = "select steps: 0-quit;"
468 "1-GetConfig; 2-AppendSurface;"
469 "3-SetMediaFormat; 4-Start;"
470 "5-Stop; 6-ListDevice;"
471 "7-Play; 8-Pause;"
472 "9-Close; 10-SetSceneType;"
473 "11-Mute; 12-UnMute";
474
475 std::shared_ptr<WfdSinkDemo> demo = std::make_shared<WfdSinkDemo>();
476 if (!demo->CreateClient()) {
477 printf("create client failed");
478 return -1;
479 }
480 std::string inputCmd;
481 while (1) {
482 printf("%s", helpNotice.c_str());
483 getline(std::cin, inputCmd);
484 if (inputCmd == "") {
485 continue;
486 } else if (inputCmd == "0") {
487 break;
488 } else {
489 if (cmdMap.count(inputCmd) == 0) {
490 printf("no cmd: %s, input again", inputCmd.c_str());
491 continue;
492 } else {
493 demo->DoCmd(cmdMap[inputCmd]);
494 }
495 }
496 }
497
498 return 0;
499 }
500
main()501 int main()
502 {
503 printf("wfd sink test start!");
504 TestOneByOne();
505 return 0;
506 }