rtcpreceivingsession.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. #if RTC_ENABLE_MEDIA
  20. #include "rtcpreceivingsession.hpp"
  21. #include "track.hpp"
  22. #include "impl/logcounter.hpp"
  23. #include <cmath>
  24. #include <utility>
  25. #ifdef _WIN32
  26. #include <winsock2.h>
  27. #else
  28. #include <arpa/inet.h>
  29. #endif
  30. namespace rtc {
  31. static impl::LogCounter COUNTER_BAD_RTP_HEADER(plog::warning, "Number of malformed RTP headers");
  32. static impl::LogCounter COUNTER_UNKNOWN_PPID(plog::warning, "Number of Unknown PPID messages");
  33. static impl::LogCounter COUNTER_BAD_NOTIF_LEN(plog::warning,
  34. "Number of Bad-Lengthed notifications");
  35. static impl::LogCounter COUNTER_BAD_SCTP_STATUS(plog::warning,
  36. "Number of unknown SCTP_STATUS errors");
  37. message_ptr RtcpReceivingSession::outgoing(message_ptr ptr) { return ptr; }
  38. message_ptr RtcpReceivingSession::incoming(message_ptr ptr) {
  39. if (ptr->type == Message::Type::Binary) {
  40. auto rtp = reinterpret_cast<const RTP *>(ptr->data());
  41. // https://tools.ietf.org/html/rfc3550#appendix-A.1
  42. if (rtp->version() != 2) {
  43. COUNTER_BAD_RTP_HEADER++;
  44. PLOG_VERBOSE << "RTP packet is not version 2";
  45. return nullptr;
  46. }
  47. if (rtp->payloadType() == 201 || rtp->payloadType() == 200) {
  48. COUNTER_BAD_RTP_HEADER++;
  49. PLOG_VERBOSE << "RTP packet has a payload type indicating RR/SR";
  50. return nullptr;
  51. }
  52. // Padding-processing is a user-level thing
  53. mSsrc = rtp->ssrc();
  54. return ptr;
  55. }
  56. assert(ptr->type == Message::Type::Control);
  57. auto rr = reinterpret_cast<const RTCP_RR *>(ptr->data());
  58. if (rr->header.payloadType() == 201) {
  59. // RR
  60. mSsrc = rr->senderSSRC();
  61. rr->log();
  62. } else if (rr->header.payloadType() == 200) {
  63. // SR
  64. mSsrc = rr->senderSSRC();
  65. auto sr = reinterpret_cast<const RTCP_SR *>(ptr->data());
  66. mSyncRTPTS = sr->rtpTimestamp();
  67. mSyncNTPTS = sr->ntpTimestamp();
  68. sr->log();
  69. // TODO For the time being, we will send RR's/REMB's when we get an SR
  70. pushRR(0);
  71. if (mRequestedBitrate > 0)
  72. pushREMB(mRequestedBitrate);
  73. }
  74. return nullptr;
  75. }
  76. void RtcpReceivingSession::requestBitrate(unsigned int newBitrate) {
  77. mRequestedBitrate = newBitrate;
  78. PLOG_DEBUG << "[GOOG-REMB] Requesting bitrate: " << newBitrate << std::endl;
  79. pushREMB(newBitrate);
  80. }
  81. void RtcpReceivingSession::pushREMB(unsigned int bitrate) {
  82. message_ptr msg = make_message(RTCP_REMB::SizeWithSSRCs(1), Message::Type::Control);
  83. auto remb = reinterpret_cast<RTCP_REMB *>(msg->data());
  84. remb->preparePacket(mSsrc, 1, bitrate);
  85. remb->setSsrc(0, mSsrc);
  86. send(msg);
  87. }
  88. void RtcpReceivingSession::pushRR(unsigned int lastSR_delay) {
  89. auto msg = make_message(RTCP_RR::SizeWithReportBlocks(1), Message::Type::Control);
  90. auto rr = reinterpret_cast<RTCP_RR *>(msg->data());
  91. rr->preparePacket(mSsrc, 1);
  92. rr->getReportBlock(0)->preparePacket(mSsrc, 0, 0, uint16_t(mGreatestSeqNo), 0, 0, mSyncNTPTS,
  93. lastSR_delay);
  94. rr->log();
  95. send(msg);
  96. }
  97. bool RtcpReceivingSession::send(message_ptr msg) {
  98. try {
  99. outgoingCallback(std::move(msg));
  100. return true;
  101. } catch (const std::exception &e) {
  102. LOG_DEBUG << "RTCP tx failed: " << e.what();
  103. }
  104. return false;
  105. }
  106. bool RtcpReceivingSession::requestKeyframe() {
  107. pushPLI();
  108. return true; // TODO Make this false when it is impossible (i.e. Opus).
  109. }
  110. void RtcpReceivingSession::pushPLI() {
  111. auto msg = make_message(RTCP_PLI::Size(), Message::Type::Control);
  112. auto *pli = reinterpret_cast<RTCP_PLI *>(msg->data());
  113. pli->preparePacket(mSsrc);
  114. send(msg);
  115. }
  116. } // namespace rtc
  117. #endif // RTC_ENABLE_MEDIA