1e0e9324cSopenharmony_ci/* 2e0e9324cSopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3e0e9324cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e0e9324cSopenharmony_ci * you may not use this file except in compliance with the License. 5e0e9324cSopenharmony_ci * You may obtain a copy of the License at 6e0e9324cSopenharmony_ci * 7e0e9324cSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e0e9324cSopenharmony_ci * 9e0e9324cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e0e9324cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e0e9324cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e0e9324cSopenharmony_ci * See the License for the specific language governing permissions and 13e0e9324cSopenharmony_ci * limitations under the License. 14e0e9324cSopenharmony_ci */ 15e0e9324cSopenharmony_ci 16e0e9324cSopenharmony_ci#include "wfd_demo.h" 17e0e9324cSopenharmony_ci#include <cstdint> 18e0e9324cSopenharmony_ci#include <functional> 19e0e9324cSopenharmony_ci#include <iostream> 20e0e9324cSopenharmony_ci#include <mutex> 21e0e9324cSopenharmony_ci#include <string> 22e0e9324cSopenharmony_ci#include <vector> 23e0e9324cSopenharmony_ci#include "extend/magic_enum/magic_enum.hpp" 24e0e9324cSopenharmony_ci#include "impl/scene/wfd/wfd_def.h" 25e0e9324cSopenharmony_ci#include "math.h" 26e0e9324cSopenharmony_ci#include "surface.h" 27e0e9324cSopenharmony_ci#include "surface_utils.h" 28e0e9324cSopenharmony_ci#include "transaction/rs_transaction.h" 29e0e9324cSopenharmony_ci#include "ui/rs_surface_node.h" 30e0e9324cSopenharmony_ci#include "utils/utils.h" 31e0e9324cSopenharmony_ci#include "window.h" 32e0e9324cSopenharmony_ci#include "window_option.h" 33e0e9324cSopenharmony_ci 34e0e9324cSopenharmony_ciusing namespace OHOS; 35e0e9324cSopenharmony_ciusing namespace OHOS::Sharing; 36e0e9324cSopenharmony_ci 37e0e9324cSopenharmony_ciVideoFormat DEFAULT_VIDEO_FORMAT = VideoFormat::VIDEO_1920X1080_30; 38e0e9324cSopenharmony_ciAudioFormat DEFAULT_AUDIO_FORMAT = AudioFormat::AUDIO_48000_16_2; 39e0e9324cSopenharmony_ciint32_t DEFAULT_WINDOW_WIDTH = 1920; 40e0e9324cSopenharmony_ciint32_t DEFAULT_WINDOW_HEIGHT = 1080; 41e0e9324cSopenharmony_cistd::vector<std::pair<int32_t, int32_t>> position{{0, 0}, {960, 0}, {0, 540}, {960, 540}}; 42e0e9324cSopenharmony_ci 43e0e9324cSopenharmony_cibool WfdDemo::Init(const WfdMode mode) 44e0e9324cSopenharmony_ci{ 45e0e9324cSopenharmony_ci std::cout << "to get wifi display " << std::string(magic_enum::enum_name(mode)).c_str() << '\n'; 46e0e9324cSopenharmony_ci client_ = MiracastFactory::GetInstance(mode); 47e0e9324cSopenharmony_ci if (!client_) { 48e0e9324cSopenharmony_ci std::cout << "create wfd client error\n"; 49e0e9324cSopenharmony_ci return false; 50e0e9324cSopenharmony_ci } 51e0e9324cSopenharmony_ci client_->SetListener(shared_from_this()); 52e0e9324cSopenharmony_ci 53e0e9324cSopenharmony_ci // when mode is SINK, init a window to display 54e0e9324cSopenharmony_ci if (mode == SINK) { 55e0e9324cSopenharmony_ci InitWindow(); 56e0e9324cSopenharmony_ci WifiDisplayTable_.emplace("Play", std::bind(&WifiDisplay::Play, client_, std::placeholders::_1)); 57e0e9324cSopenharmony_ci WifiDisplayTable_.emplace("Pause", std::bind(&WifiDisplay::Pause, client_, std::placeholders::_1)); 58e0e9324cSopenharmony_ci WifiDisplayTable_.emplace("Close", std::bind(&WifiDisplay::Close, client_, std::placeholders::_1)); 59e0e9324cSopenharmony_ci } 60e0e9324cSopenharmony_ci return true; 61e0e9324cSopenharmony_ci} 62e0e9324cSopenharmony_ci 63e0e9324cSopenharmony_civoid WfdDemo::InitWindow() 64e0e9324cSopenharmony_ci{ 65e0e9324cSopenharmony_ci if (!surfaceIds_.empty()) 66e0e9324cSopenharmony_ci return; 67e0e9324cSopenharmony_ci std::cout << "create window enter\n"; 68e0e9324cSopenharmony_ci 69e0e9324cSopenharmony_ci for (int i = 0; i < windowNum_; i++) { 70e0e9324cSopenharmony_ci sptr<Rosen::WindowOption> option = new Rosen::WindowOption(); 71e0e9324cSopenharmony_ci option->SetWindowRect({position[i].first, position[i].second, DEFAULT_WINDOW_WIDTH / sqrt(windowNum_), 72e0e9324cSopenharmony_ci DEFAULT_WINDOW_HEIGHT / sqrt(windowNum_)}); 73e0e9324cSopenharmony_ci option->SetWindowType(Rosen::WindowType::WINDOW_TYPE_APP_LAUNCHING); 74e0e9324cSopenharmony_ci option->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FULLSCREEN); 75e0e9324cSopenharmony_ci sptr<Rosen::Window> window = Rosen::Window::Create("wifi display window:" + std::to_string(i), option); 76e0e9324cSopenharmony_ci auto surfaceNode = window->GetSurfaceNode(); 77e0e9324cSopenharmony_ci surfaceNode->SetFrameGravity(Rosen::Gravity::RESIZE); 78e0e9324cSopenharmony_ci Rosen::RSTransaction::FlushImplicitTransaction(); 79e0e9324cSopenharmony_ci sptr<Surface> surface = surfaceNode->GetSurface(); 80e0e9324cSopenharmony_ci window->SetRequestedOrientation(Rosen::Orientation::HORIZONTAL); 81e0e9324cSopenharmony_ci window->Show(); 82e0e9324cSopenharmony_ci auto surfaceId = surface->GetUniqueId(); 83e0e9324cSopenharmony_ci surfaceIds_.push_back(surfaceId); 84e0e9324cSopenharmony_ci int ret = SurfaceUtils::GetInstance()->Add(surfaceId, surface); 85e0e9324cSopenharmony_ci if (ret != 0) 86e0e9324cSopenharmony_ci std::cout << "add failed\n"; 87e0e9324cSopenharmony_ci devicesIsPlaying_.push_back(""); 88e0e9324cSopenharmony_ci } 89e0e9324cSopenharmony_ci} 90e0e9324cSopenharmony_ci 91e0e9324cSopenharmony_civoid WfdDemo::SelectMediaFormat() 92e0e9324cSopenharmony_ci{ 93e0e9324cSopenharmony_ci videoAttr_.codecType = CodecType::CODEC_H264; 94e0e9324cSopenharmony_ci videoAttr_.format = 7; 95e0e9324cSopenharmony_ci audioAttr_.codecType = CodecType::CODEC_AAC; 96e0e9324cSopenharmony_ci audioAttr_.format = 43; 97e0e9324cSopenharmony_ci 98e0e9324cSopenharmony_ci std::cout << "please input videoFormatId:(default 4)\n"; 99e0e9324cSopenharmony_ci std::cout << "0: VIDEO_640X480_60\n"; 100e0e9324cSopenharmony_ci std::cout << "1: VIDEO_1280X720_25\n"; 101e0e9324cSopenharmony_ci std::cout << "2: VIDEO_1280X720_30\n"; 102e0e9324cSopenharmony_ci std::cout << "4: VIDEO_1920X1080_25\n"; 103e0e9324cSopenharmony_ci std::cout << "5: VIDEO_1920X1080_30\n"; 104e0e9324cSopenharmony_ci 105e0e9324cSopenharmony_ci std::string input; 106e0e9324cSopenharmony_ci getline(std::cin, input); 107e0e9324cSopenharmony_ci if (input != "") { 108e0e9324cSopenharmony_ci videoAttr_.format = static_cast<VideoFormat>(atoi(input.c_str()) + 2); 109e0e9324cSopenharmony_ci } 110e0e9324cSopenharmony_ci 111e0e9324cSopenharmony_ci std::cout << "please input audioFormatId:\n(default 13)"; 112e0e9324cSopenharmony_ci std::cout << "0: AUDIO_44100_8_1\n"; 113e0e9324cSopenharmony_ci std::cout << "1: AUDIO_44100_8_2\n"; 114e0e9324cSopenharmony_ci std::cout << "2: AUDIO_44100_16_1\n"; 115e0e9324cSopenharmony_ci std::cout << "3: AUDIO_44100_16_2\n"; 116e0e9324cSopenharmony_ci std::cout << "10: AUDIO_48000_8_1\n"; 117e0e9324cSopenharmony_ci std::cout << "11: AUDIO_48000_8_2\n"; 118e0e9324cSopenharmony_ci std::cout << "12: AUDIO_48000_16_1\n"; 119e0e9324cSopenharmony_ci std::cout << "13: AUDIO_48000_16_2\n"; 120e0e9324cSopenharmony_ci 121e0e9324cSopenharmony_ci getline(std::cin, input); 122e0e9324cSopenharmony_ci if (input != "") { 123e0e9324cSopenharmony_ci audioAttr_.format = static_cast<AudioFormat>(atoi(input.c_str()) + 30); 124e0e9324cSopenharmony_ci } 125e0e9324cSopenharmony_ci} 126e0e9324cSopenharmony_ci 127e0e9324cSopenharmony_civoid WfdDemo::AddDevice() {} 128e0e9324cSopenharmony_civoid WfdDemo::RemoveDevice() {} 129e0e9324cSopenharmony_ci 130e0e9324cSopenharmony_civoid WfdDemo::OnError(const CastErrorInfo &errorInfo) 131e0e9324cSopenharmony_ci{ 132e0e9324cSopenharmony_ci std::cout << "on error. deviceId : " << errorInfo.deviceId << ", errorCode : " << errorInfo.errorCode << '\n'; 133e0e9324cSopenharmony_ci} 134e0e9324cSopenharmony_ci 135e0e9324cSopenharmony_civoid WfdDemo::OnDeviceState(const CastDeviceInfo &deviceInfo) 136e0e9324cSopenharmony_ci{ 137e0e9324cSopenharmony_ci switch (deviceInfo.state) { 138e0e9324cSopenharmony_ci case CastDeviceState::CONNECTED: { 139e0e9324cSopenharmony_ci { 140e0e9324cSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 141e0e9324cSopenharmony_ci for (int item = 0; item < windowNum_; item++) { 142e0e9324cSopenharmony_ci if (devicesIsPlaying_[item] == "") { 143e0e9324cSopenharmony_ci client_->AppendSurface(deviceInfo.deviceId, surfaceIds_[item]); 144e0e9324cSopenharmony_ci client_->SetMediaFormat(deviceInfo.deviceId, videoAttr_, audioAttr_); 145e0e9324cSopenharmony_ci client_->Play(deviceInfo.deviceId); 146e0e9324cSopenharmony_ci devicesIsPlaying_[item] = deviceInfo.deviceId; 147e0e9324cSopenharmony_ci break; 148e0e9324cSopenharmony_ci } 149e0e9324cSopenharmony_ci } 150e0e9324cSopenharmony_ci break; 151e0e9324cSopenharmony_ci } 152e0e9324cSopenharmony_ci } 153e0e9324cSopenharmony_ci case CastDeviceState::DISCONNECTED: { 154e0e9324cSopenharmony_ci { 155e0e9324cSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 156e0e9324cSopenharmony_ci for (int item = 0; item < windowNum_; item++) { 157e0e9324cSopenharmony_ci if (devicesIsPlaying_[item] == deviceInfo.deviceId) { 158e0e9324cSopenharmony_ci devicesIsPlaying_[item] = ""; 159e0e9324cSopenharmony_ci } 160e0e9324cSopenharmony_ci } 161e0e9324cSopenharmony_ci break; 162e0e9324cSopenharmony_ci } 163e0e9324cSopenharmony_ci } 164e0e9324cSopenharmony_ci default: 165e0e9324cSopenharmony_ci break; 166e0e9324cSopenharmony_ci } 167e0e9324cSopenharmony_ci std::cout << "on OnConnectionChanged : \n"; 168e0e9324cSopenharmony_ci std::cout << "ip : " << deviceInfo.ipAddr.c_str() << '\n'; 169e0e9324cSopenharmony_ci std::cout << "mac : " << deviceInfo.deviceId.c_str() << '\n'; 170e0e9324cSopenharmony_ci std::cout << "state: " << std::string(magic_enum::enum_name(deviceInfo.state)).c_str() << '\n'; 171e0e9324cSopenharmony_ci} 172e0e9324cSopenharmony_ci 173e0e9324cSopenharmony_civoid WfdDemo::OnDeviceFound(const std::vector<CastDeviceInfo> &deviceInfos) 174e0e9324cSopenharmony_ci{ 175e0e9324cSopenharmony_ci for (int deviceNum = 0; deviceNum < deviceInfos.size(); deviceNum++) { 176e0e9324cSopenharmony_ci std::cout << deviceNum << ". device id : " << deviceInfos[deviceNum].deviceId 177e0e9324cSopenharmony_ci << " device name : " << deviceInfos[deviceNum].deviceName << "\n"; 178e0e9324cSopenharmony_ci } 179e0e9324cSopenharmony_ci} 180e0e9324cSopenharmony_ci 181e0e9324cSopenharmony_civoid WfdDemo::RunWfdSink() 182e0e9324cSopenharmony_ci{ 183e0e9324cSopenharmony_ci if (!Init(SINK)) 184e0e9324cSopenharmony_ci return; 185e0e9324cSopenharmony_ci 186e0e9324cSopenharmony_ci if (client_->Start() == 0) { 187e0e9324cSopenharmony_ci std::cout << "wifi display sink service start!\n"; 188e0e9324cSopenharmony_ci } 189e0e9324cSopenharmony_ci SelectMediaFormat(); 190e0e9324cSopenharmony_ci 191e0e9324cSopenharmony_ci std::map<std::string, std::string> cmdMap = {{"1", "Start"}, {"2", "Stop"}, {"3", "SelectMediaFormat"}, 192e0e9324cSopenharmony_ci {"4", "Play"}, {"5", "Pause"}, {"6", "Close"}, 193e0e9324cSopenharmony_ci {"12", "ListDevice"}}; 194e0e9324cSopenharmony_ci 195e0e9324cSopenharmony_ci std::string helpNotice = "select steps: 0-quit;\n" 196e0e9324cSopenharmony_ci "1-Start; 2-Stop;\n" 197e0e9324cSopenharmony_ci "3-SelectMediaFormat; 4-Play;\n" 198e0e9324cSopenharmony_ci "5-Pause; 6-Close;\n" 199e0e9324cSopenharmony_ci "12-ListDevice\n"; 200e0e9324cSopenharmony_ci 201e0e9324cSopenharmony_ci std::string inputCmd; 202e0e9324cSopenharmony_ci while (1) { 203e0e9324cSopenharmony_ci std::cout << helpNotice; 204e0e9324cSopenharmony_ci getline(std::cin, inputCmd); 205e0e9324cSopenharmony_ci if (inputCmd == "") { 206e0e9324cSopenharmony_ci continue; 207e0e9324cSopenharmony_ci } else if (inputCmd == "0") { 208e0e9324cSopenharmony_ci break; 209e0e9324cSopenharmony_ci } else { 210e0e9324cSopenharmony_ci if (cmdMap.count(inputCmd) == 0) { 211e0e9324cSopenharmony_ci std::cout << "no cmd: " << inputCmd << ", input agin\n"; 212e0e9324cSopenharmony_ci continue; 213e0e9324cSopenharmony_ci } else { 214e0e9324cSopenharmony_ci DoCmd(cmdMap[inputCmd]); 215e0e9324cSopenharmony_ci } 216e0e9324cSopenharmony_ci } 217e0e9324cSopenharmony_ci } 218e0e9324cSopenharmony_ci} 219e0e9324cSopenharmony_ci 220e0e9324cSopenharmony_civoid WfdDemo::RunWfdSource() {} 221e0e9324cSopenharmony_ci 222e0e9324cSopenharmony_civoid WfdDemo::DoCmd(std::string cmd) 223e0e9324cSopenharmony_ci{ 224e0e9324cSopenharmony_ci if (!client_) 225e0e9324cSopenharmony_ci return; 226e0e9324cSopenharmony_ci if (cmd.find("Start") != std::string::npos) { 227e0e9324cSopenharmony_ci client_->Start(); 228e0e9324cSopenharmony_ci } else if (cmd.find("Stop") != std::string::npos) { 229e0e9324cSopenharmony_ci client_->Stop(); 230e0e9324cSopenharmony_ci { 231e0e9324cSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 232e0e9324cSopenharmony_ci for (int item = 0; item < devicesIsPlaying_.size(); item++) 233e0e9324cSopenharmony_ci devicesIsPlaying_[item] = ""; 234e0e9324cSopenharmony_ci } 235e0e9324cSopenharmony_ci } else if (WifiDisplayTable_.find(cmd) != WifiDisplayTable_.end()) { 236e0e9324cSopenharmony_ci std::cout << "enter the window number to operate: \n"; 237e0e9324cSopenharmony_ci int32_t winNum = 0; 238e0e9324cSopenharmony_ci std::string input; 239e0e9324cSopenharmony_ci getline(std::cin, input); 240e0e9324cSopenharmony_ci if (input != "") { 241e0e9324cSopenharmony_ci winNum = static_cast<int32_t>(atoi(input.c_str())); 242e0e9324cSopenharmony_ci if (winNum >= windowNum_) { 243e0e9324cSopenharmony_ci std::cout << "the window not exits\n"; 244e0e9324cSopenharmony_ci return; 245e0e9324cSopenharmony_ci } 246e0e9324cSopenharmony_ci } 247e0e9324cSopenharmony_ci auto iter = WifiDisplayTable_.find(cmd); 248e0e9324cSopenharmony_ci auto func = iter->second; 249e0e9324cSopenharmony_ci func(devicesIsPlaying_[winNum]); 250e0e9324cSopenharmony_ci } else if (cmd.find("SelectMediaFormat") != std::string::npos) { 251e0e9324cSopenharmony_ci SelectMediaFormat(); 252e0e9324cSopenharmony_ci } else if (cmd.find("StartDiscover") != std::string::npos) { 253e0e9324cSopenharmony_ci client_->StartDiscover(); 254e0e9324cSopenharmony_ci } else if (cmd.find("StopDiscover") != std::string::npos) { 255e0e9324cSopenharmony_ci client_->StopDiscover(); 256e0e9324cSopenharmony_ci } else if (cmd.find("AddDevice") != std::string::npos) { 257e0e9324cSopenharmony_ci CastDeviceInfo info; 258e0e9324cSopenharmony_ci client_->AddDevice(info); 259e0e9324cSopenharmony_ci } else if (cmd.find("RemoveDevice") != std::string::npos) { 260e0e9324cSopenharmony_ci client_->RemoveDevice("0.0.0.0"); 261e0e9324cSopenharmony_ci } else { 262e0e9324cSopenharmony_ci std::cout << "operation is invalid\n"; 263e0e9324cSopenharmony_ci } 264e0e9324cSopenharmony_ci 265e0e9324cSopenharmony_ci return; 266e0e9324cSopenharmony_ci} 267e0e9324cSopenharmony_ci 268e0e9324cSopenharmony_ciint main() 269e0e9324cSopenharmony_ci{ 270e0e9324cSopenharmony_ci std::cout << "Please select a demo scenario number(default sink): \n"; 271e0e9324cSopenharmony_ci std::cout << "0:wfd sink\n"; 272e0e9324cSopenharmony_ci std::cout << "1:wfd source\n"; 273e0e9324cSopenharmony_ci 274e0e9324cSopenharmony_ci auto wifiDisplay = std::make_shared<WfdDemo>(); 275e0e9324cSopenharmony_ci 276e0e9324cSopenharmony_ci std::string mode; 277e0e9324cSopenharmony_ci (void)getline(std::cin, mode); 278e0e9324cSopenharmony_ci if (mode == "" || mode == "0") { 279e0e9324cSopenharmony_ci wifiDisplay->RunWfdSink(); 280e0e9324cSopenharmony_ci } else if (mode == "1") { 281e0e9324cSopenharmony_ci wifiDisplay->RunWfdSource(); 282e0e9324cSopenharmony_ci } else { 283e0e9324cSopenharmony_ci std::cout << "no that selection\n"; 284e0e9324cSopenharmony_ci return 0; 285e0e9324cSopenharmony_ci } 286e0e9324cSopenharmony_ci 287e0e9324cSopenharmony_ci std::cout << "wfd test end!\n"; 288e0e9324cSopenharmony_ci return 0; 289e0e9324cSopenharmony_ci}