[feat] update sr and rr implementation

This commit is contained in:
dijunkun
2025-02-17 17:32:20 +08:00
parent 71b9c78dd5
commit 4aa9925e56
15 changed files with 577 additions and 17 deletions

View File

@@ -0,0 +1,5 @@
#include "rtcp_receiver.h"
RtcpReceiver::RtcpReceiver() {}
RtcpReceiver::~RtcpReceiver() {}

View File

@@ -0,0 +1,19 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-02-17
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _RTCP_RECEIVER_H_
#define _RTCP_RECEIVER_H_
class RtcpReceiver {
public:
RtcpReceiver();
~RtcpReceiver();
public:
private:
}
#endif

View File

@@ -0,0 +1,43 @@
#include "rtcp_sender.h"
RtcpSender::RtcpSender(std::shared_ptr<webrtc::Clock> clock, uint32_t ssrc)
: clock_(clock), ssrc_(ssrc) {}
RtcpSender::~RtcpSender() {}
void RtcpSender::BuildSR(const RtcpContext& ctx, PacketSender& sender) {
// The timestamp of this RTCP packet should be estimated as the timestamp of
// the frame being captured at this moment. We are calculating that
// timestamp as the last frame's timestamp + the time since the last frame
// was captured.
int rtp_rate = rtp_clock_rates_khz_[last_payload_type_];
if (rtp_rate <= 0) {
rtp_rate =
(audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) /
1000;
}
// Round now_us_ to the closest millisecond, because Ntp time is rounded
// when converted to milliseconds,
uint32_t rtp_timestamp =
timestamp_offset_ + last_rtp_timestamp_ +
((ctx.now_.us() + 500) / 1000 - last_frame_capture_time_->ms()) *
rtp_rate;
rtcp::SenderReport report;
report.SetSenderSsrc(ssrc_);
report.SetNtp(env_.clock().ConvertTimestampToNtpTime(ctx.now_));
report.SetRtpTimestamp(rtp_timestamp);
report.SetPacketCount(ctx.feedback_state_.packets_sent);
report.SetOctetCount(ctx.feedback_state_.media_bytes_sent);
report.SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
sender.AppendPacket(report);
}
void RtcpSender::BuildRR(const RtcpContext& ctx, PacketSender& sender) {
rtcp::ReceiverReport report;
report.SetSenderSsrc(ssrc_);
report.SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
if (method_ == RtcpMode::kCompound || !report.report_blocks().empty()) {
sender.AppendPacket(report);
}
}

View File

@@ -0,0 +1,26 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-02-17
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _RTCP_SENDER_H_
#define _RTCP_SENDER_H_
#include <memory>
#include "api/clock/clock.h"
#include "rtcp/rtcp_packet/rtcp_packet.h"
class RtcpSender {
public:
RtcpSender(std::shared_ptr<webrtc::Clock> clock, uint32_t ssrc);
~RtcpSender();
public:
private:
std::shared_ptr<webrtc::Clock> clock_;
uint32_t ssrc_;
}
#endif

View File

@@ -261,7 +261,7 @@ size_t CongestionControlFeedback::BlockLength() const {
return total_size; return total_size;
} }
bool CongestionControlFeedback::Parse(const rtcp::CommonHeader& packet) { bool CongestionControlFeedback::Parse(const CommonHeader& packet) {
const uint8_t* payload = packet.payload(); const uint8_t* payload = packet.payload();
const uint8_t* payload_end = packet.payload() + packet.payload_size_bytes(); const uint8_t* payload_end = packet.payload() + packet.payload_size_bytes();

View File

@@ -13,8 +13,6 @@
#include "byte_io.h" #include "byte_io.h"
#include "log.h" #include "log.h"
namespace webrtc {
namespace rtcp {
// 0 1 1 2 3 // 0 1 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -83,5 +81,3 @@ bool CommonHeader::Parse(const uint8_t* buffer, size_t size_bytes) {
} }
return true; return true;
} }
} // namespace rtcp
} // namespace webrtc

View File

@@ -13,8 +13,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
namespace webrtc {
namespace rtcp {
class CommonHeader { class CommonHeader {
public: public:
static constexpr size_t kHeaderSizeBytes = 4; static constexpr size_t kHeaderSizeBytes = 4;
@@ -47,6 +45,5 @@ class CommonHeader {
uint32_t payload_size_ = 0; uint32_t payload_size_ = 0;
const uint8_t* payload_ = nullptr; const uint8_t* payload_ = nullptr;
}; };
} // namespace rtcp
} // namespace webrtc
#endif // MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_COMMON_HEADER_H_ #endif // MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_COMMON_HEADER_H_

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "receiver_report.h"
#include <utility>
#include "byte_io.h"
#include "common_header.h"
#include "log.h"
// RTCP receiver report (RFC 3550).
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |V=2|P| RC | PT=RR=201 | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC of packet sender |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | report block(s) |
// | .... |
ReceiverReport::ReceiverReport() = default;
ReceiverReport::ReceiverReport(const ReceiverReport& rhs) = default;
ReceiverReport::~ReceiverReport() = default;
bool ReceiverReport::Parse(const CommonHeader& packet) {
const uint8_t report_blocks_count = packet.count();
if (packet.payload_size_bytes() <
kRrBaseLength + report_blocks_count * ReportBlock::kLength) {
LOG_WARN("Packet is too small to contain all the data.");
return false;
}
SetSenderSsrc(ByteReader<uint32_t>::ReadBigEndian(packet.payload()));
const uint8_t* next_report_block = packet.payload() + kRrBaseLength;
report_blocks_.resize(report_blocks_count);
for (ReportBlock& block : report_blocks_) {
block.Parse(next_report_block, ReportBlock::kLength);
next_report_block += ReportBlock::kLength;
}
return true;
}
size_t ReceiverReport::BlockLength() const {
return kHeaderLength + kRrBaseLength +
report_blocks_.size() * ReportBlock::kLength;
}
bool ReceiverReport::Create(uint8_t* packet, size_t* index, size_t max_length,
PacketReadyCallback callback) const {
while (*index + BlockLength() > max_length) {
if (!OnBufferFull(packet, index, callback)) return false;
}
CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet,
index);
ByteWriter<uint32_t>::WriteBigEndian(packet + *index, sender_ssrc());
*index += kRrBaseLength;
for (const ReportBlock& block : report_blocks_) {
block.Create(packet + *index);
*index += ReportBlock::kLength;
}
return true;
}
bool ReceiverReport::AddReportBlock(const ReportBlock& block) {
if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
LOG_WARN("Max report blocks reached.");
return false;
}
report_blocks_.push_back(block);
return true;
}
bool ReceiverReport::SetReportBlocks(std::vector<ReportBlock> blocks) {
if (blocks.size() > kMaxNumberOfReportBlocks) {
LOG_WARN("Too many report blocks ({}) for receiver report.", blocks.size());
return false;
}
report_blocks_ = std::move(blocks);
return true;
}

View File

@@ -0,0 +1,50 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-02-17
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _RECEIVER_REPORT_H_
#define _RECEIVER_REPORT_H_
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include "report_block.h"
#include "rtcp_packet.h"
class CommonHeader;
class ReceiverReport : public RtcpPacket {
public:
static constexpr uint8_t kPacketType = 201;
static constexpr size_t kMaxNumberOfReportBlocks = 0x1f;
ReceiverReport();
ReceiverReport(const ReceiverReport&);
~ReceiverReport() override;
// Parse assumes header is already parsed and validated.
bool Parse(const CommonHeader& packet);
bool AddReportBlock(const ReportBlock& block);
bool SetReportBlocks(std::vector<ReportBlock> blocks);
const std::vector<ReportBlock>& report_blocks() const {
return report_blocks_;
}
size_t BlockLength() const override;
bool Create(uint8_t* packet, size_t* index, size_t max_length,
PacketReadyCallback callback) const override;
private:
static constexpr size_t kRrBaseLength = 4;
std::vector<ReportBlock> report_blocks_;
};
#endif

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "report_block.h"
#include "byte_io.h"
#include "log.h"
// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
//
// RTCP report block (RFC 3550).
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 0 | SSRC_1 (SSRC of first source) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 4 | fraction lost | cumulative number of packets lost |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 8 | extended highest sequence number received |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 12 | interarrival jitter |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 16 | last SR (LSR) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 20 | delay since last SR (DLSR) |
// 24 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
ReportBlock::ReportBlock()
: source_ssrc_(0),
fraction_lost_(0),
cumulative_lost_(0),
extended_high_seq_num_(0),
jitter_(0),
last_sr_(0),
delay_since_last_sr_(0) {}
bool ReportBlock::Parse(const uint8_t* buffer, size_t length) {
if (length < ReportBlock::kLength) {
LOG_ERROR("Report Block should be 24 bytes long");
return false;
}
source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[0]);
fraction_lost_ = buffer[4];
cumulative_lost_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[5]);
extended_high_seq_num_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
jitter_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[12]);
last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[16]);
delay_since_last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[20]);
return true;
}
void ReportBlock::Create(uint8_t* buffer) const {
ByteWriter<uint32_t>::WriteBigEndian(&buffer[0], source_ssrc());
ByteWriter<uint8_t>::WriteBigEndian(&buffer[4], fraction_lost());
ByteWriter<int32_t, 3>::WriteBigEndian(&buffer[5], cumulative_lost());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[8], extended_high_seq_num());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[12], jitter());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[16], last_sr());
ByteWriter<uint32_t>::WriteBigEndian(&buffer[20], delay_since_last_sr());
}
bool ReportBlock::SetCumulativeLost(int32_t cumulative_lost) {
// We have only 3 bytes to store it, and it's a signed value.
if (cumulative_lost >= (1 << 23) || cumulative_lost < -(1 << 23)) {
LOG_WARN("Cumulative lost is too big to fit into Report Block");
return false;
}
cumulative_lost_ = cumulative_lost;
return true;
}

View File

@@ -0,0 +1,60 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-02-17
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _REPORT_BLOCK_H_
#define _REPORT_BLOCK_H_
#include <stddef.h>
#include <stdint.h>
// A ReportBlock represents the Sender Report packet from
// RFC 3550 section 6.4.1.
class ReportBlock {
public:
static constexpr size_t kLength = 24;
ReportBlock();
~ReportBlock() {}
bool Parse(const uint8_t* buffer, size_t length);
// Fills buffer with the ReportBlock.
// Consumes ReportBlock::kLength bytes.
void Create(uint8_t* buffer) const;
void SetMediaSsrc(uint32_t ssrc) { source_ssrc_ = ssrc; }
void SetFractionLost(uint8_t fraction_lost) {
fraction_lost_ = fraction_lost;
}
bool SetCumulativeLost(int32_t cumulative_lost);
void SetExtHighestSeqNum(uint32_t ext_highest_seq_num) {
extended_high_seq_num_ = ext_highest_seq_num;
}
void SetJitter(uint32_t jitter) { jitter_ = jitter; }
void SetLastSr(uint32_t last_sr) { last_sr_ = last_sr; }
void SetDelayLastSr(uint32_t delay_last_sr) {
delay_since_last_sr_ = delay_last_sr;
}
uint32_t source_ssrc() const { return source_ssrc_; }
uint8_t fraction_lost() const { return fraction_lost_; }
int32_t cumulative_lost() const { return cumulative_lost_; }
uint32_t extended_high_seq_num() const { return extended_high_seq_num_; }
uint32_t jitter() const { return jitter_; }
uint32_t last_sr() const { return last_sr_; }
uint32_t delay_since_last_sr() const { return delay_since_last_sr_; }
private:
uint32_t source_ssrc_; // 32 bits
uint8_t fraction_lost_; // 8 bits representing a fixed point value 0..1
int32_t cumulative_lost_; // Signed 24-bit value
uint32_t extended_high_seq_num_; // 32 bits
uint32_t jitter_; // 32 bits
uint32_t last_sr_; // 32 bits
uint32_t delay_since_last_sr_; // 32 bits, units of 1/65536 seconds
};
#endif

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "sender_report.h"
#include <utility>
#include "byte_io.h"
#include "common_header.h"
#include "log.h"
// Sender report (SR) (RFC 3550).
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |V=2|P| RC | PT=SR=200 | length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 0 | SSRC of sender |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 4 | NTP timestamp, most significant word |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 8 | NTP timestamp, least significant word |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 12 | RTP timestamp |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 16 | sender's packet count |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 20 | sender's octet count |
// 24 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
SenderReport::SenderReport()
: rtp_timestamp_(0), sender_packet_count_(0), sender_octet_count_(0) {}
SenderReport::SenderReport(const SenderReport&) = default;
SenderReport::SenderReport(SenderReport&&) = default;
SenderReport& SenderReport::operator=(const SenderReport&) = default;
SenderReport& SenderReport::operator=(SenderReport&&) = default;
SenderReport::~SenderReport() = default;
bool SenderReport::Parse(const CommonHeader& packet) {
const uint8_t report_block_count = packet.count();
if (packet.payload_size_bytes() <
kSenderBaseLength + report_block_count * ReportBlock::kLength) {
LOG_WARN("Packet is too small to contain all the data.");
return false;
}
// Read SenderReport header.
const uint8_t* const payload = packet.payload();
SetSenderSsrc(ByteReader<uint32_t>::ReadBigEndian(&payload[0]));
uint32_t secs = ByteReader<uint32_t>::ReadBigEndian(&payload[4]);
uint32_t frac = ByteReader<uint32_t>::ReadBigEndian(&payload[8]);
ntp_.Set(secs, frac);
rtp_timestamp_ = ByteReader<uint32_t>::ReadBigEndian(&payload[12]);
sender_packet_count_ = ByteReader<uint32_t>::ReadBigEndian(&payload[16]);
sender_octet_count_ = ByteReader<uint32_t>::ReadBigEndian(&payload[20]);
report_blocks_.resize(report_block_count);
const uint8_t* next_block = payload + kSenderBaseLength;
for (ReportBlock& block : report_blocks_) {
bool block_parsed = block.Parse(next_block, ReportBlock::kLength);
next_block += ReportBlock::kLength;
}
return true;
}
size_t SenderReport::BlockLength() const {
return kHeaderLength + kSenderBaseLength +
report_blocks_.size() * ReportBlock::kLength;
}
bool SenderReport::Create(uint8_t* packet, size_t* index, size_t max_length,
PacketReadyCallback callback) const {
while (*index + BlockLength() > max_length) {
if (!OnBufferFull(packet, index, callback)) return false;
}
const size_t index_end = *index + BlockLength();
CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet,
index);
// Write SenderReport header.
ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 0], sender_ssrc());
ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 4], ntp_.seconds());
ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 8], ntp_.fractions());
ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 12], rtp_timestamp_);
ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 16],
sender_packet_count_);
ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 20],
sender_octet_count_);
*index += kSenderBaseLength;
// Write report blocks.
for (const ReportBlock& block : report_blocks_) {
block.Create(packet + *index);
*index += ReportBlock::kLength;
}
return true;
}
bool SenderReport::AddReportBlock(const ReportBlock& block) {
if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
LOG_WARN("Max report blocks reached.");
return false;
}
report_blocks_.push_back(block);
return true;
}
bool SenderReport::SetReportBlocks(std::vector<ReportBlock> blocks) {
if (blocks.size() > kMaxNumberOfReportBlocks) {
LOG_WARN("Too many report blocks ({}) for sender report.", blocks.size());
return false;
}
report_blocks_ = std::move(blocks);
return true;
}

View File

@@ -0,0 +1,71 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-02-17
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _SENDER_REPORT_H_
#define _SENDER_REPORT_H_
#include <vector>
#include "api/ntp/ntp_time.h"
#include "report_block.h"
#include "rtcp_packet.h"
class CommonHeader;
class SenderReport : public RtcpPacket {
public:
static constexpr uint8_t kPacketType = 200;
static constexpr size_t kMaxNumberOfReportBlocks = 0x1f;
SenderReport();
SenderReport(const SenderReport&);
SenderReport(SenderReport&&);
SenderReport& operator=(const SenderReport&);
SenderReport& operator=(SenderReport&&);
~SenderReport() override;
// Parse assumes header is already parsed and validated.
bool Parse(const CommonHeader& packet);
void SetNtp(webrtc::NtpTime ntp) { ntp_ = ntp; }
void SetRtpTimestamp(uint32_t rtp_timestamp) {
rtp_timestamp_ = rtp_timestamp;
}
void SetPacketCount(uint32_t packet_count) {
sender_packet_count_ = packet_count;
}
void SetOctetCount(uint32_t octet_count) {
sender_octet_count_ = octet_count;
}
bool AddReportBlock(const ReportBlock& block);
bool SetReportBlocks(std::vector<ReportBlock> blocks);
void ClearReportBlocks() { report_blocks_.clear(); }
webrtc::NtpTime ntp() const { return ntp_; }
uint32_t rtp_timestamp() const { return rtp_timestamp_; }
uint32_t sender_packet_count() const { return sender_packet_count_; }
uint32_t sender_octet_count() const { return sender_octet_count_; }
const std::vector<ReportBlock>& report_blocks() const {
return report_blocks_;
}
size_t BlockLength() const override;
bool Create(uint8_t* packet, size_t* index, size_t max_length,
PacketReadyCallback callback) const override;
private:
static constexpr size_t kSenderBaseLength = 24;
webrtc::NtpTime ntp_;
uint32_t rtp_timestamp_;
uint32_t sender_packet_count_;
uint32_t sender_octet_count_;
std::vector<ReportBlock> report_blocks_;
};
#endif

View File

@@ -207,7 +207,7 @@ void IceTransport::OnReceiveBuffer(NiceAgent *agent, guint stream_id,
bool IceTransport::ParseRtcpPacket(const uint8_t *buffer, size_t size, bool IceTransport::ParseRtcpPacket(const uint8_t *buffer, size_t size,
RtcpPacketInfo *rtcp_packet_info) { RtcpPacketInfo *rtcp_packet_info) {
webrtc::rtcp::CommonHeader rtcp_block; CommonHeader rtcp_block;
// If a sender report is received but no DLRR, we need to reset the // If a sender report is received but no DLRR, we need to reset the
// roundTripTime stat according to the standard, see // roundTripTime stat according to the standard, see
// https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-roundtriptime // https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-roundtriptime
@@ -300,8 +300,7 @@ bool IceTransport::ParseRtcpPacket(const uint8_t *buffer, size_t size,
} }
bool IceTransport::HandleCongestionControlFeedback( bool IceTransport::HandleCongestionControlFeedback(
const webrtc::rtcp::CommonHeader &rtcp_block, const CommonHeader &rtcp_block, RtcpPacketInfo *rtcp_packet_info) {
RtcpPacketInfo *rtcp_packet_info) {
webrtc::rtcp::CongestionControlFeedback feedback; webrtc::rtcp::CongestionControlFeedback feedback;
if (!feedback.Parse(rtcp_block) || feedback.packets().empty()) { if (!feedback.Parse(rtcp_block) || feedback.packets().empty()) {
return false; return false;
@@ -318,7 +317,7 @@ bool IceTransport::HandleCongestionControlFeedback(
return true; return true;
} }
bool IceTransport::HandleNack(const webrtc::rtcp::CommonHeader &rtcp_block, bool IceTransport::HandleNack(const CommonHeader &rtcp_block,
RtcpPacketInfo *rtcp_packet_info) { RtcpPacketInfo *rtcp_packet_info) {
webrtc::rtcp::Nack nack; webrtc::rtcp::Nack nack;
if (!nack.Parse(rtcp_block)) { if (!nack.Parse(rtcp_block)) {

View File

@@ -128,11 +128,10 @@ class IceTransport {
bool ParseRtcpPacket(const uint8_t *buffer, size_t size, bool ParseRtcpPacket(const uint8_t *buffer, size_t size,
RtcpPacketInfo *rtcp_packet_info); RtcpPacketInfo *rtcp_packet_info);
bool HandleCongestionControlFeedback( bool HandleCongestionControlFeedback(const CommonHeader &rtcp_block,
const webrtc::rtcp::CommonHeader &rtcp_block, RtcpPacketInfo *rtcp_packet_info);
RtcpPacketInfo *rtcp_packet_info);
bool HandleNack(const webrtc::rtcp::CommonHeader &rtcp_block, bool HandleNack(const CommonHeader &rtcp_block,
RtcpPacketInfo *rtcp_packet_info); RtcpPacketInfo *rtcp_packet_info);
private: private: