blob: 6feb55da57999ff700121f18bbd83a98a653ef3f [file] [log] [blame]
Danil Chapovalov398a7c62017-10-24 17:07:05 +02001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "modules/rtp_rtcp/source/rtcp_transceiver_impl.h"
12
13#include <utility>
14#include <vector>
15
16#include "api/call/transport.h"
17#include "modules/rtp_rtcp/include/receive_statistics.h"
18#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
19#include "modules/rtp_rtcp/source/rtcp_packet.h"
20#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
21#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
22#include "rtc_base/checks.h"
23
24namespace webrtc {
25namespace {
26
27// Helper to put several RTCP packets into lower layer datagram composing
28// Compound or Reduced-Size RTCP packet, as defined by RFC 5506 section 2.
29class PacketSender : public rtcp::RtcpPacket::PacketReadyCallback {
30 public:
31 PacketSender(Transport* transport, size_t max_packet_size)
32 : transport_(transport), max_packet_size_(max_packet_size) {
33 RTC_CHECK_LE(max_packet_size, IP_PACKET_SIZE);
34 }
35 ~PacketSender() override {
36 RTC_DCHECK_EQ(index_, 0) << "Unsent rtcp packet.";
37 }
38
39 // Appends a packet to pending compound packet.
40 // Sends rtcp compound packet if buffer was already full and resets buffer.
41 void AppendPacket(const rtcp::RtcpPacket& packet) {
42 packet.Create(buffer_, &index_, max_packet_size_, this);
43 }
44
45 // Sends pending rtcp compound packet.
46 void Send() {
47 if (index_ > 0) {
48 OnPacketReady(buffer_, index_);
49 index_ = 0;
50 }
51 }
52
53 private:
54 // Implements RtcpPacket::PacketReadyCallback
55 void OnPacketReady(uint8_t* data, size_t length) override {
56 transport_->SendRtcp(data, length);
57 }
58
59 Transport* const transport_;
60 const size_t max_packet_size_;
61 size_t index_ = 0;
62 uint8_t buffer_[IP_PACKET_SIZE];
63};
64
65} // namespace
66
67RtcpTransceiverImpl::RtcpTransceiverImpl(const RtcpTransceiverConfig& config)
68 : config_(config) {
69 RTC_CHECK(config_.Validate());
70}
71
72RtcpTransceiverImpl::~RtcpTransceiverImpl() = default;
73
74void RtcpTransceiverImpl::SendCompoundPacket() {
75 PacketSender sender(config_.outgoing_transport, config_.max_packet_size);
76
77 rtcp::ReceiverReport rr;
78 rr.SetSenderSsrc(config_.feedback_ssrc);
79 if (config_.receive_statistics) {
80 // TODO(danilchap): Support sending more than
81 // |ReceiverReport::kMaxNumberOfReportBlocks| per compound rtcp packet.
82 std::vector<rtcp::ReportBlock> report_blocks =
83 config_.receive_statistics->RtcpReportBlocks(
84 rtcp::ReceiverReport::kMaxNumberOfReportBlocks);
85 // TODO(danilchap): Fill in LastSr/DelayLastSr fields of report blocks
86 // when RtcpTransceiver handles incoming sender reports.
87 rr.SetReportBlocks(std::move(report_blocks));
88 }
89 sender.AppendPacket(rr);
90 // TODO(danilchap): Append SDES to conform to the requirements on minimal
91 // compound RTCP packet.
92
93 sender.Send();
94}
95
96} // namespace webrtc