mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[fix] fix receiver report building and parsing
This commit is contained in:
@@ -29,7 +29,9 @@ class AudioChannelSend {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SendAudio(char *data, size_t size);
|
||||
int SendAudio(char* data, size_t size);
|
||||
|
||||
void OnReceiverReport(const ReceiverReport& receiver_report) {}
|
||||
|
||||
private:
|
||||
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
|
||||
|
||||
@@ -29,7 +29,9 @@ class DataChannelSend {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SendData(const char *data, size_t size);
|
||||
int SendData(const char* data, size_t size);
|
||||
|
||||
void OnReceiverReport(const ReceiverReport& receiver_report) {}
|
||||
|
||||
private:
|
||||
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <functional>
|
||||
|
||||
#include "io_statistics.h"
|
||||
#include "receiver_report.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "rtp_packet.h"
|
||||
#include "rtp_statistics.h"
|
||||
@@ -26,6 +27,7 @@ class RtpAudioSender : public ThreadBase {
|
||||
void Enqueue(std::vector<std::shared_ptr<RtpPacket>> rtp_packets);
|
||||
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
||||
uint32_t GetSsrc() { return ssrc_; }
|
||||
void OnReceiverReport(const ReceiverReport &receiver_report) {}
|
||||
|
||||
private:
|
||||
int SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <functional>
|
||||
|
||||
#include "io_statistics.h"
|
||||
#include "receiver_report.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "rtp_packet.h"
|
||||
#include "rtp_statistics.h"
|
||||
@@ -26,6 +27,7 @@ class RtpDataSender : public ThreadBase {
|
||||
void Enqueue(std::vector<std::shared_ptr<RtpPacket>> rtp_packets);
|
||||
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
||||
uint32_t GetSsrc() { return ssrc_; }
|
||||
void OnReceiverReport(const ReceiverReport &receiver_report) {}
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
@@ -101,33 +101,16 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
|
||||
webrtc::Timestamp now = clock_->CurrentTime();
|
||||
remote_ssrc_ = rtp_packet.Ssrc();
|
||||
uint16_t sequence_number = rtp_packet.SequenceNumber();
|
||||
if (last_receive_time_.has_value() == 0) {
|
||||
extended_high_seq_num_ = sequence_number;
|
||||
--cumulative_loss_;
|
||||
if (!last_receive_time_.has_value()) {
|
||||
last_extended_high_seq_num_ = sequence_number - 1;
|
||||
extended_high_seq_num_ = sequence_number - 1;
|
||||
}
|
||||
|
||||
cumulative_loss_ += sequence_number - extended_high_seq_num_;
|
||||
extended_high_seq_num_ = sequence_number;
|
||||
|
||||
// Calculate fraction lost.
|
||||
int64_t exp_since_last = extended_high_seq_num_ - last_extended_high_seq_num_;
|
||||
int32_t lost_since_last = cumulative_loss_ - last_report_cumulative_loss_;
|
||||
if (exp_since_last > 0 && lost_since_last > 0) {
|
||||
// Scale 0 to 255, where 255 is 100% loss.
|
||||
fraction_lost_ = 255 * lost_since_last / exp_since_last;
|
||||
}
|
||||
cumulative_lost_ = cumulative_loss_ + cumulative_loss_rtcp_offset_;
|
||||
if (cumulative_lost_ < 0) {
|
||||
// Clamp to zero. Work around to accommodate for senders that misbehave with
|
||||
// negative cumulative loss.
|
||||
cumulative_lost_ = 0;
|
||||
cumulative_loss_rtcp_offset_ = -cumulative_loss_;
|
||||
}
|
||||
if (cumulative_lost_ > 0x7fffff) {
|
||||
// Packets lost is a 24 bit signed field, and thus should be clamped, as
|
||||
// described in https://datatracker.ietf.org/doc/html/rfc3550#appendix-A.3
|
||||
cumulative_lost_ = 0x7fffff;
|
||||
}
|
||||
|
||||
if (rtp_packet_received.Timestamp() != last_received_timestamp_) {
|
||||
webrtc::TimeDelta receive_diff = now - *last_receive_time_;
|
||||
uint32_t receive_diff_rtp =
|
||||
(receive_diff * rtp_packet_received.payload_type_frequency())
|
||||
@@ -149,9 +132,8 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
|
||||
}
|
||||
|
||||
jitter_ = jitter_q4_ >> 4;
|
||||
}
|
||||
|
||||
last_extended_high_seq_num_ = extended_high_seq_num_;
|
||||
last_report_cumulative_loss_ = cumulative_loss_;
|
||||
last_received_timestamp_ = rtp_packet_received.Timestamp();
|
||||
last_receive_time_ = now;
|
||||
|
||||
@@ -592,24 +574,50 @@ void RtpVideoReceiver::ReviseFrequencyAndJitter(int payload_type_frequency) {
|
||||
|
||||
void RtpVideoReceiver::SendRR() {
|
||||
uint32_t now = CompactNtp(clock_->CurrentNtpTime());
|
||||
|
||||
// Calculate fraction lost.
|
||||
int64_t exp_since_last = extended_high_seq_num_ - last_extended_high_seq_num_;
|
||||
int32_t lost_since_last = cumulative_loss_ - last_report_cumulative_loss_;
|
||||
if (exp_since_last > 0 && lost_since_last > 0) {
|
||||
// Scale 0 to 255, where 255 is 100% loss.
|
||||
fraction_lost_ = 255 * lost_since_last / exp_since_last;
|
||||
} else {
|
||||
fraction_lost_ = 0;
|
||||
}
|
||||
|
||||
cumulative_lost_ = cumulative_loss_ + cumulative_loss_rtcp_offset_;
|
||||
if (cumulative_lost_ < 0) {
|
||||
// Clamp to zero. Work around to accommodate for senders that misbehave with
|
||||
// negative cumulative loss.
|
||||
cumulative_lost_ = 0;
|
||||
cumulative_loss_rtcp_offset_ = -cumulative_loss_;
|
||||
}
|
||||
if (cumulative_lost_ > 0x7fffff) {
|
||||
// Packets lost is a 24 bit signed field, and thus should be clamped, as
|
||||
// described in https://datatracker.ietf.org/doc/html/rfc3550#appendix-A.3
|
||||
cumulative_lost_ = 0x7fffff;
|
||||
}
|
||||
|
||||
uint32_t receive_time = last_arrival_ntp_timestamp;
|
||||
uint32_t delay_since_last_sr = now - receive_time;
|
||||
|
||||
ReceiverReport rtcp_rr;
|
||||
RtcpReportBlock report;
|
||||
|
||||
report.SetMediaSsrc(ssrc_);
|
||||
report.SetMediaSsrc(fraction_lost_);
|
||||
report.SetMediaSsrc(remote_ssrc_);
|
||||
report.SetFractionLost(fraction_lost_);
|
||||
report.SetCumulativeLost(cumulative_lost_);
|
||||
report.SetExtHighestSeqNum(extended_high_seq_num_);
|
||||
report.SetJitter(jitter_);
|
||||
report.SetLastSr(last_remote_ntp_timestamp);
|
||||
report.SetDelayLastSr(delay_since_last_sr);
|
||||
|
||||
rtcp_rr.SetSenderSsrc(ssrc_);
|
||||
rtcp_rr.SetReportBlock(report);
|
||||
|
||||
rtcp_rr.Build();
|
||||
SendRtcpRR(rtcp_rr);
|
||||
|
||||
last_extended_high_seq_num_ = extended_high_seq_num_;
|
||||
last_report_cumulative_loss_ = cumulative_loss_;
|
||||
}
|
||||
|
||||
void RtpVideoReceiver::RtcpThread() {
|
||||
@@ -626,7 +634,7 @@ void RtpVideoReceiver::RtcpThread() {
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_send_rtcp_rr_ts_)
|
||||
.count();
|
||||
if (elapsed >= rtcp_rr_interval_ms_) {
|
||||
if (elapsed >= rtcp_rr_interval_ms_ && last_receive_time_.has_value()) {
|
||||
SendRR();
|
||||
last_send_rtcp_rr_ts_ = now;
|
||||
}
|
||||
|
||||
@@ -174,3 +174,15 @@ bool RtpVideoSender::Process() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RtpVideoSender::OnReceiverReport(const ReceiverReport& receiver_report) {
|
||||
std::vector<RtcpReportBlock> reports = receiver_report.GetReportBlocks();
|
||||
|
||||
for (auto r : reports) {
|
||||
LOG_WARN(
|
||||
"r_ssrc [{}], f_lost [{}], c_lost [{}], h_seq [{}], jitter [{}], "
|
||||
"lsr [{}], dlsr [{}] ",
|
||||
r.SourceSsrc(), r.FractionLost() / 255.0, r.CumulativeLost(),
|
||||
r.ExtendedHighSeqNum(), r.Jitter(), r.LastSr(), r.DelaySinceLastSr());
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "api/clock/clock.h"
|
||||
#include "clock/system_clock.h"
|
||||
#include "io_statistics.h"
|
||||
#include "receiver_report.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "rtp_packet.h"
|
||||
#include "rtp_packet_history.h"
|
||||
@@ -28,6 +29,7 @@ class RtpVideoSender : public ThreadBase {
|
||||
void SetOnSentPacketFunc(
|
||||
std::function<void(const webrtc::RtpPacketToSend &)> on_sent_packet_func);
|
||||
uint32_t GetSsrc() { return ssrc_; }
|
||||
void OnReceiverReport(const ReceiverReport &receiver_report);
|
||||
|
||||
private:
|
||||
int SendRtpPacket(
|
||||
|
||||
@@ -45,6 +45,12 @@ class VideoChannelSend {
|
||||
Timestamp recv_ts,
|
||||
const webrtc::rtcp::CongestionControlFeedback& feedback);
|
||||
|
||||
void OnReceiverReport(const ReceiverReport& receiver_report) {
|
||||
if (rtp_video_sender_) {
|
||||
rtp_video_sender_->OnReceiverReport(receiver_report);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void PostUpdates(webrtc::NetworkControlUpdate update);
|
||||
void UpdateControlState();
|
||||
|
||||
@@ -21,7 +21,7 @@ void ReceiverReport::SetReportBlocks(
|
||||
|
||||
const uint8_t *ReceiverReport::Build() {
|
||||
size_t buffer_size =
|
||||
DEFAULT_SR_SIZE + reports_.size() * RtcpReportBlock::kLength;
|
||||
DEFAULT_RR_SIZE + reports_.size() * RtcpReportBlock::kLength;
|
||||
if (!buffer_ || buffer_size != size_) {
|
||||
delete[] buffer_;
|
||||
buffer_ = nullptr;
|
||||
@@ -34,6 +34,12 @@ const uint8_t *ReceiverReport::Build() {
|
||||
rtcp_common_header_.Create(DEFAULT_RTCP_VERSION, 0, DEFAULT_RR_BLOCK_NUM,
|
||||
RTCP_TYPE::RR, DEFAULT_RR_SIZE, buffer_);
|
||||
|
||||
buffer_[pos] = sender_ssrc_ >> 24 & 0xFF;
|
||||
buffer_[pos + 1] = sender_ssrc_ >> 16 & 0xFF;
|
||||
buffer_[pos + 2] = sender_ssrc_ >> 8 & 0xFF;
|
||||
buffer_[pos + 3] = sender_ssrc_ & 0xFF;
|
||||
pos += 4;
|
||||
|
||||
for (const auto &report : reports_) {
|
||||
pos += report.Create(buffer_ + pos);
|
||||
}
|
||||
@@ -43,12 +49,18 @@ const uint8_t *ReceiverReport::Build() {
|
||||
|
||||
size_t ReceiverReport::Parse(const RtcpCommonHeader &packet) {
|
||||
reports_.clear();
|
||||
size_t pos = packet.payload_size_bytes();
|
||||
rtcp_common_header_ = packet;
|
||||
|
||||
for (int i = 0; i < rtcp_common_header_.fmt(); i++) {
|
||||
const uint8_t *payload = packet.payload();
|
||||
const uint8_t *payload_end = packet.payload() + packet.payload_size_bytes();
|
||||
size_t pos = 0;
|
||||
sender_ssrc_ = (payload[pos] << 24) + (payload[pos + 1] << 16) +
|
||||
(payload[pos + 2] << 8) + payload[pos + 3];
|
||||
pos += 4;
|
||||
while (payload + pos < payload_end) {
|
||||
RtcpReportBlock report;
|
||||
pos += report.Parse(buffer_ + pos);
|
||||
reports_.emplace_back(std::move(report));
|
||||
pos += report.Parse(payload + pos);
|
||||
reports_.push_back(std::move(report));
|
||||
}
|
||||
|
||||
return pos;
|
||||
|
||||
@@ -45,9 +45,13 @@ class ReceiverReport {
|
||||
~ReceiverReport();
|
||||
|
||||
public:
|
||||
void SetSenderSsrc(uint32_t ssrc) { sender_ssrc_ = ssrc; }
|
||||
void SetReportBlock(RtcpReportBlock &rtcp_report_block);
|
||||
void SetReportBlocks(std::vector<RtcpReportBlock> &rtcp_report_blocks);
|
||||
|
||||
uint32_t SenderSsrc() const { return sender_ssrc_; }
|
||||
std::vector<RtcpReportBlock> GetReportBlocks() const { return reports_; }
|
||||
|
||||
const uint8_t *Build();
|
||||
size_t Parse(const RtcpCommonHeader &packet);
|
||||
|
||||
@@ -55,6 +59,7 @@ class ReceiverReport {
|
||||
size_t Size() const { return size_; }
|
||||
|
||||
private:
|
||||
uint32_t sender_ssrc_;
|
||||
RtcpCommonHeader rtcp_common_header_;
|
||||
std::vector<RtcpReportBlock> reports_;
|
||||
|
||||
|
||||
@@ -64,7 +64,10 @@ class SenderReport {
|
||||
~SenderReport();
|
||||
|
||||
public:
|
||||
void SetSenderSsrc(uint32_t ssrc) { sender_info_.sender_ssrc = ssrc; }
|
||||
void SetSenderSsrc(uint32_t ssrc) {
|
||||
sender_ssrc_ = ssrc;
|
||||
sender_info_.sender_ssrc = ssrc;
|
||||
}
|
||||
void SetNtpTimestamp(uint64_t ntp_timestamp) {
|
||||
sender_info_.ntp_ts_msw =
|
||||
ntp_timestamp / webrtc::NtpTime::kFractionsPerSecond;
|
||||
@@ -81,7 +84,7 @@ class SenderReport {
|
||||
void SetReportBlock(RtcpReportBlock &rtcp_report_block);
|
||||
void SetReportBlocks(std::vector<RtcpReportBlock> &rtcp_report_blocks);
|
||||
|
||||
uint32_t SenderSsrc() const { return sender_info_.sender_ssrc; }
|
||||
uint32_t SenderSsrc() const { return sender_ssrc_; }
|
||||
uint32_t NtpTimestamp() const {
|
||||
return (sender_info_.ntp_ts_msw << 16) | sender_info_.ntp_ts_lsw >> 16;
|
||||
}
|
||||
@@ -100,6 +103,7 @@ class SenderReport {
|
||||
size_t Size() const { return size_; }
|
||||
|
||||
private:
|
||||
uint32_t sender_ssrc_;
|
||||
RtcpCommonHeader rtcp_common_header_;
|
||||
SenderInfo sender_info_;
|
||||
std::vector<RtcpReportBlock> reports_;
|
||||
|
||||
@@ -230,8 +230,7 @@ bool IceTransport::ParseRtcpPacket(const uint8_t *buffer, size_t size,
|
||||
// received_blocks[rtcp_packet_info->remote_ssrc].sender_report = true;
|
||||
break;
|
||||
case RtcpPacket::RtcpPayloadType::RR:
|
||||
LOG_INFO("Receiver report");
|
||||
// valid = HandleReceiverReport(rtcp_block, rtcp_packet_info);
|
||||
valid = HandleReceiverReport(rtcp_block, rtcp_packet_info);
|
||||
break;
|
||||
case RtpFeedback::kPacketType:
|
||||
switch (rtcp_block.fmt()) {
|
||||
@@ -313,6 +312,19 @@ bool IceTransport::HandleSenderReport(const RtcpCommonHeader &rtcp_block,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IceTransport::HandleReceiverReport(const RtcpCommonHeader &rtcp_block,
|
||||
RtcpPacketInfo *rtcp_packet_info) {
|
||||
ReceiverReport receiver_report;
|
||||
if (!receiver_report.Parse(rtcp_block)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ice_transport_controller_) {
|
||||
ice_transport_controller_->OnReceiverReport(receiver_report);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IceTransport::HandleCongestionControlFeedback(
|
||||
const RtcpCommonHeader &rtcp_block, RtcpPacketInfo *rtcp_packet_info) {
|
||||
webrtc::rtcp::CongestionControlFeedback feedback;
|
||||
|
||||
@@ -133,6 +133,9 @@ class IceTransport {
|
||||
bool HandleSenderReport(const RtcpCommonHeader &rtcp_block,
|
||||
RtcpPacketInfo *rtcp_packet_info);
|
||||
|
||||
bool HandleReceiverReport(const RtcpCommonHeader &rtcp_block,
|
||||
RtcpPacketInfo *rtcp_packet_info);
|
||||
|
||||
bool HandleCongestionControlFeedback(const RtcpCommonHeader &rtcp_block,
|
||||
RtcpPacketInfo *rtcp_packet_info);
|
||||
|
||||
|
||||
@@ -338,6 +338,13 @@ void IceTransportController::OnSenderReport(const SenderReport& sender_report) {
|
||||
data_channel_receive_->OnSenderReport(sender_report);
|
||||
}
|
||||
|
||||
void IceTransportController::OnReceiverReport(
|
||||
const ReceiverReport& receiver_report) {
|
||||
video_channel_send_->OnReceiverReport(receiver_report);
|
||||
audio_channel_send_->OnReceiverReport(receiver_report);
|
||||
data_channel_send_->OnReceiverReport(receiver_report);
|
||||
}
|
||||
|
||||
void IceTransportController::OnCongestionControlFeedback(
|
||||
const webrtc::rtcp::CongestionControlFeedback& feedback) {
|
||||
std::optional<webrtc::TransportPacketsFeedback> feedback_msg =
|
||||
|
||||
@@ -62,6 +62,7 @@ class IceTransportController
|
||||
|
||||
public:
|
||||
void OnSenderReport(const SenderReport &sender_report);
|
||||
void OnReceiverReport(const ReceiverReport& receiver_report);
|
||||
void OnCongestionControlFeedback(
|
||||
const webrtc::rtcp::CongestionControlFeedback &feedback);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user