rtcp.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /**
  2. * Copyright (c) 2020 Staz Modrzynski
  3. * Copyright (c) 2020 Paul-Louis Ageneau
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include "rtcp.hpp"
  20. #include <cmath>
  21. #include <utility>
  22. #include "track.hpp"
  23. #ifdef _WIN32
  24. #include <winsock2.h>
  25. #else
  26. #include <arpa/inet.h>
  27. #endif
  28. namespace rtc {
  29. rtc::message_ptr RtcpReceivingSession::outgoing(rtc::message_ptr ptr) {
  30. return ptr;
  31. }
  32. rtc::message_ptr RtcpReceivingSession::incoming(rtc::message_ptr ptr) {
  33. if (ptr->type == rtc::Message::Type::Binary) {
  34. auto rtp = reinterpret_cast<const RTP *>(ptr->data());
  35. // https://tools.ietf.org/html/rfc3550#appendix-A.1
  36. if (rtp->version() != 2) {
  37. PLOG_WARNING << "RTP packet is not version 2";
  38. return nullptr;
  39. }
  40. if (rtp->payloadType() == 201 || rtp->payloadType() == 200) {
  41. PLOG_WARNING << "RTP packet has a payload type indicating RR/SR";
  42. return nullptr;
  43. }
  44. // TODO Implement the padding bit
  45. if (rtp->padding()) {
  46. PLOG_WARNING << "Padding processing not implemented";
  47. }
  48. mSsrc = rtp->ssrc();
  49. return ptr;
  50. }
  51. assert(ptr->type == rtc::Message::Type::Control);
  52. auto rr = reinterpret_cast<const RTCP_RR *>(ptr->data());
  53. if (rr->header.payloadType() == 201) {
  54. // RR
  55. mSsrc = rr->senderSSRC();
  56. rr->log();
  57. } else if (rr->header.payloadType() == 200) {
  58. // SR
  59. mSsrc = rr->senderSSRC();
  60. auto sr = reinterpret_cast<const RTCP_SR *>(ptr->data());
  61. mSyncRTPTS = sr->rtpTimestamp();
  62. mSyncNTPTS = sr->ntpTimestamp();
  63. sr->log();
  64. // TODO For the time being, we will send RR's/REMB's when we get an SR
  65. pushRR(0);
  66. if (mRequestedBitrate > 0)
  67. pushREMB(mRequestedBitrate);
  68. }
  69. return nullptr;
  70. }
  71. void RtcpReceivingSession::requestBitrate(unsigned int newBitrate) {
  72. mRequestedBitrate = newBitrate;
  73. PLOG_DEBUG << "[GOOG-REMB] Requesting bitrate: " << newBitrate << std::endl;
  74. pushREMB(newBitrate);
  75. }
  76. void RtcpReceivingSession::pushREMB(unsigned int bitrate) {
  77. rtc::message_ptr msg =
  78. rtc::make_message(RTCP_REMB::sizeWithSSRCs(1), rtc::Message::Type::Control);
  79. auto remb = reinterpret_cast<RTCP_REMB *>(msg->data());
  80. remb->preparePacket(mSsrc, 1, bitrate);
  81. remb->setSsrc(0, mSsrc);
  82. send(msg);
  83. }
  84. void RtcpReceivingSession::pushRR(unsigned int lastSR_delay) {
  85. auto msg = rtc::make_message(RTCP_RR::sizeWithReportBlocks(1), rtc::Message::Type::Control);
  86. auto rr = reinterpret_cast<RTCP_RR *>(msg->data());
  87. rr->preparePacket(mSsrc, 1);
  88. rr->getReportBlock(0)->preparePacket(mSsrc, 0, 0, uint16_t(mGreatestSeqNo), 0, 0, mSyncNTPTS,
  89. lastSR_delay);
  90. rr->log();
  91. send(msg);
  92. }
  93. bool RtcpReceivingSession::send(message_ptr msg) {
  94. try {
  95. outgoingCallback(std::move(msg));
  96. return true;
  97. } catch (const std::exception &e) {
  98. LOG_DEBUG << "RTCP tx failed: " << e.what();
  99. }
  100. return false;
  101. }
  102. bool RtcpReceivingSession::requestKeyframe() {
  103. pushPLI();
  104. return true; // TODO Make this false when it is impossible (i.e. Opus).
  105. }
  106. void RtcpReceivingSession::pushPLI() {
  107. auto msg = rtc::make_message(rtc::RTCP_PLI::size(), rtc::Message::Type::Control);
  108. auto *pli = (rtc::RTCP_PLI *) msg->data();
  109. pli->preparePacket(mSsrc);
  110. send(msg);
  111. }
  112. void RtcpHandler::onOutgoing(const std::function<void(rtc::message_ptr)>& cb) {
  113. this->outgoingCallback = synchronized_callback<rtc::message_ptr>(cb);
  114. }
  115. } // namespace rtc