main.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * libdatachannel media sender example
  3. * Copyright (c) 2020 Staz Modrzynski
  4. * Copyright (c) 2020 Paul-Louis Ageneau
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "rtc/rtc.hpp"
  20. #include <cstddef>
  21. #include <iostream>
  22. #include <memory>
  23. #include <stdexcept>
  24. #include <utility>
  25. #include <nlohmann/json.hpp>
  26. #ifdef _WIN32
  27. #define _WINSOCK_DEPRECATED_NO_WARNINGS
  28. #include <winsock2.h>
  29. #else
  30. #include <arpa/inet.h>
  31. #include <netinet/in.h>
  32. #include <sys/socket.h>
  33. typedef int SOCKET;
  34. #endif
  35. using nlohmann::json;
  36. const int BUFFER_SIZE = 2048;
  37. int main() {
  38. try {
  39. rtc::InitLogger(rtc::LogLevel::Debug);
  40. auto pc = std::make_shared<rtc::PeerConnection>();
  41. pc->onStateChange(
  42. [](rtc::PeerConnection::State state) { std::cout << "State: " << state << std::endl; });
  43. pc->onGatheringStateChange([pc](rtc::PeerConnection::GatheringState state) {
  44. std::cout << "Gathering State: " << state << std::endl;
  45. if (state == rtc::PeerConnection::GatheringState::Complete) {
  46. auto description = pc->localDescription();
  47. json message = {{"type", description->typeString()},
  48. {"sdp", std::string(description.value())}};
  49. std::cout << message << std::endl;
  50. }
  51. });
  52. SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
  53. struct sockaddr_in addr = {};
  54. addr.sin_family = AF_INET;
  55. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  56. addr.sin_port = htons(6000);
  57. if (bind(sock, reinterpret_cast<const sockaddr *>(&addr), sizeof(addr)) < 0)
  58. throw std::runtime_error("Failed to bind UDP socket on 127.0.0.1:6000");
  59. int rcvBufSize = 212992;
  60. setsockopt(sock, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char *>(&rcvBufSize),
  61. sizeof(rcvBufSize));
  62. const rtc::SSRC ssrc = 42;
  63. rtc::Description::Video media("video", rtc::Description::Direction::SendOnly);
  64. media.addH264Codec(96); // Must match the payload type of the external h264 RTP stream
  65. media.addSSRC(ssrc, "video-send");
  66. auto track = pc->addTrack(media);
  67. pc->setLocalDescription();
  68. std::cout << "RTP video stream expected on localhost:6000" << std::endl;
  69. std::cout << "Please copy/paste the answer provided by the browser: " << std::endl;
  70. std::string sdp;
  71. std::getline(std::cin, sdp);
  72. json j = json::parse(sdp);
  73. rtc::Description answer(j["sdp"].get<std::string>(), j["type"].get<std::string>());
  74. pc->setRemoteDescription(answer);
  75. // Receive from UDP
  76. char buffer[BUFFER_SIZE];
  77. int len;
  78. while ((len = recv(sock, buffer, BUFFER_SIZE, 0)) >= 0) {
  79. if (len < sizeof(rtc::RtpHeader) || !track->isOpen())
  80. continue;
  81. auto rtp = reinterpret_cast<rtc::RtpHeader *>(buffer);
  82. rtp->setSsrc(ssrc);
  83. track->send(reinterpret_cast<const std::byte *>(buffer), len);
  84. }
  85. } catch (const std::exception &e) {
  86. std::cerr << "Error: " << e.what() << std::endl;
  87. }
  88. }