/*
* libdatachannel media sender 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 .
*/
#include "rtc/rtc.hpp"
#include
#include
#include
#include
#include
#include
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#else
#include
#include
#include
typedef int SOCKET;
#endif
using nlohmann::json;
const int BUFFER_SIZE = 2048;
int main() {
try {
rtc::InitLogger(rtc::LogLevel::Debug);
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 << message << std::endl;
}
});
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6000);
if (bind(sock, reinterpret_cast(&addr), sizeof(addr)) < 0)
throw std::runtime_error("Failed to bind UDP socket on 127.0.0.1:6000");
int rcvBufSize = 212992;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&rcvBufSize),
sizeof(rcvBufSize));
const rtc::SSRC ssrc = 42;
rtc::Description::Video media("video", rtc::Description::Direction::SendOnly);
media.addH264Codec(96); // Must match the payload type of the external h264 RTP stream
media.addSSRC(ssrc, "video-send");
auto track = pc->addTrack(media);
pc->setLocalDescription();
std::cout << "RTP video stream expected on localhost:6000" << std::endl;
std::cout << "Please copy/paste the answer provided by the browser: " << std::endl;
std::string sdp;
std::getline(std::cin, sdp);
json j = json::parse(sdp);
rtc::Description answer(j["sdp"].get(), j["type"].get());
pc->setRemoteDescription(answer);
// Receive from UDP
char buffer[BUFFER_SIZE];
int len;
while ((len = recv(sock, buffer, BUFFER_SIZE, 0)) >= 0) {
if (len < sizeof(rtc::RtpHeader) || !track->isOpen())
continue;
auto rtp = reinterpret_cast(buffer);
rtp->setSsrc(ssrc);
track->send(reinterpret_cast(buffer), len);
}
} catch (const std::exception &e) {
std::cerr << "Error: " << e.what() << std::endl;
}
}