rtcp.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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->getSenderSSRC();
  56. rr->log();
  57. } else if (rr->header.payloadType() == 200) {
  58. // SR
  59. mSsrc = rr->getSenderSSRC();
  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. // remb->log();
  83. send(msg);
  84. }
  85. void RtcpReceivingSession::pushRR(unsigned int lastSR_delay) {
  86. auto msg = rtc::make_message(RTCP_RR::sizeWithReportBlocks(1), rtc::Message::Type::Control);
  87. auto rr = reinterpret_cast<RTCP_RR *>(msg->data());
  88. rr->preparePacket(mSsrc, 1);
  89. rr->getReportBlock(0)->preparePacket(mSsrc, 0, 0, mGreatestSeqNo, 0, 0, mSyncNTPTS,
  90. lastSR_delay);
  91. rr->log();
  92. send(msg);
  93. }
  94. bool RtcpReceivingSession::send(message_ptr msg) {
  95. try {
  96. outgoingCallback(std::move(msg));
  97. return true;
  98. } catch (const std::exception &e) {
  99. LOG_DEBUG << "RTCP tx failed: " << e.what();
  100. }
  101. return false;
  102. }
  103. void RtcpHandler::onOutgoing(const std::function<void(rtc::message_ptr)>& cb) {
  104. this->outgoingCallback = synchronized_callback<rtc::message_ptr>(cb);
  105. }
  106. } // namespace rtc