/* * libdatachannel client example * Copyright (c) 2020 Staz Modrzynski * Copyright (c) 2020 Paul-Louis Ageneau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; If not, see . */ #define _WINSOCK_DEPRECATED_NO_WARNINGS #include "rtc/rtc.hpp" #include #include #include using nlohmann::json; class Sender { rtc::PeerConnection conn; }; struct Receiver { std::shared_ptr conn; std::shared_ptr track; }; int main() { std::vector> receivers; try { rtc::InitLogger(rtc::LogLevel::Info); auto pc = std::make_shared(); pc->onStateChange( [](rtc::PeerConnection::State state) { std::cout << "State: " << state << std::endl; }); pc->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) { std::cout << "Gathering State: " << state << std::endl; if (state == rtc::PeerConnection::GatheringState::Complete) { auto description = pc->localDescription(); json message = {{"type", description->typeString()}, {"sdp", std::string(description.value())}}; std::cout << "Please copy/paste this offer to the SENDER: " << message << std::endl; } }); rtc::Description::Video media("video", rtc::Description::Direction::RecvOnly); media.addH264Codec(96); media.setBitrate(3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam) auto track = pc->addTrack(media); pc->setLocalDescription(); auto session = std::make_shared(); track->setRtcpHandler(session); const rtc::SSRC targetSSRC = 15; track->onMessage( [&receivers](rtc::binary message) { // This is an RTP packet auto rtp = (rtc::RTP*) message.data(); rtp->ssrc = htonl(targetSSRC); for (auto pc : receivers) { if (pc->track != nullptr && pc->track->isOpen()) { pc->track->send(message); } } }, nullptr); // Set the SENDERS Answer { std::cout << "Please copy/paste the answer provided by the SENDER: " << std::endl; std::string sdp; std::getline(std::cin, sdp); std::cout << "Got answer" << sdp << std::endl; json j = json::parse(sdp); rtc::Description answer(j["sdp"].get(), j["type"].get()); pc->setRemoteDescription(answer); } // For each receiver while (true) { auto pc = std::make_shared(); pc->conn = std::make_shared(); pc->conn->onStateChange( [](rtc::PeerConnection::State state) { std::cout << "State: " << state << std::endl; }); pc->conn->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) { std::cout << "Gathering State: " << state << std::endl; if (state == rtc::PeerConnection::GatheringState::Complete) { auto description = pc->conn->localDescription(); json message = {{"type", description->typeString()}, {"sdp", std::string(description.value())}}; std::cout << "Please copy/paste this offer to the RECEIVER: " << message << std::endl; } }); rtc::Description::Video media("video", rtc::Description::Direction::SendOnly); media.addH264Codec(96); media.setBitrate( 3000); // Request 3Mbps (Browsers do not encode more than 2.5MBps from a webcam) media.addSSRC(targetSSRC, "video-send"); pc->track = pc->conn->addTrack(media); pc->conn->setLocalDescription(); auto session = std::make_shared(); pc->track->setRtcpHandler(session); pc->track->onMessage([](rtc::binary var){}, nullptr); std::cout << "Please copy/paste the answer provided by the RECEIVER: " << std::endl; std::string sdp; std::getline(std::cin, sdp); std::cout << "Got answer" << sdp << std::endl; json j = json::parse(sdp); rtc::Description answer(j["sdp"].get(), j["type"].get()); pc->conn->setRemoteDescription(answer); receivers.push_back(pc); } } catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; } }