Delete SendDelayObserver interface
send delay is now measured through SendPacketObserver interface Bug: None Change-Id: I0dc3de1522e2824d9431d7e3a3dc524588687dda Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/319500 Reviewed-by: Åsa Persson <asapersson@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#40755}
This commit is contained in:
parent
745641e589
commit
3aa951a7c6
@ -57,7 +57,6 @@ struct RtpSenderObservers {
|
|||||||
BitrateStatisticsObserver* bitrate_observer;
|
BitrateStatisticsObserver* bitrate_observer;
|
||||||
FrameCountObserver* frame_count_observer;
|
FrameCountObserver* frame_count_observer;
|
||||||
RtcpPacketTypeCounterObserver* rtcp_type_observer;
|
RtcpPacketTypeCounterObserver* rtcp_type_observer;
|
||||||
SendSideDelayObserver* send_delay_observer;
|
|
||||||
SendPacketObserver* send_packet_observer;
|
SendPacketObserver* send_packet_observer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -224,7 +224,6 @@ std::vector<RtpStreamSender> CreateRtpStreamSenders(
|
|||||||
observers.report_block_data_observer;
|
observers.report_block_data_observer;
|
||||||
configuration.paced_sender = transport->packet_sender();
|
configuration.paced_sender = transport->packet_sender();
|
||||||
configuration.send_bitrate_observer = observers.bitrate_observer;
|
configuration.send_bitrate_observer = observers.bitrate_observer;
|
||||||
configuration.send_side_delay_observer = observers.send_delay_observer;
|
|
||||||
configuration.send_packet_observer = observers.send_packet_observer;
|
configuration.send_packet_observer = observers.send_packet_observer;
|
||||||
configuration.event_log = event_log;
|
configuration.event_log = event_log;
|
||||||
configuration.retransmission_rate_limiter = retransmission_rate_limiter;
|
configuration.retransmission_rate_limiter = retransmission_rate_limiter;
|
||||||
|
|||||||
@ -66,8 +66,7 @@ RtpSenderObservers CreateObservers(
|
|||||||
StreamDataCountersCallback* rtp_stats,
|
StreamDataCountersCallback* rtp_stats,
|
||||||
BitrateStatisticsObserver* bitrate_observer,
|
BitrateStatisticsObserver* bitrate_observer,
|
||||||
FrameCountObserver* frame_count_observer,
|
FrameCountObserver* frame_count_observer,
|
||||||
RtcpPacketTypeCounterObserver* rtcp_type_observer,
|
RtcpPacketTypeCounterObserver* rtcp_type_observer) {
|
||||||
SendSideDelayObserver* send_delay_observer) {
|
|
||||||
RtpSenderObservers observers;
|
RtpSenderObservers observers;
|
||||||
observers.rtcp_rtt_stats = nullptr;
|
observers.rtcp_rtt_stats = nullptr;
|
||||||
observers.intra_frame_callback = intra_frame_callback;
|
observers.intra_frame_callback = intra_frame_callback;
|
||||||
@ -77,7 +76,6 @@ RtpSenderObservers CreateObservers(
|
|||||||
observers.bitrate_observer = bitrate_observer;
|
observers.bitrate_observer = bitrate_observer;
|
||||||
observers.frame_count_observer = frame_count_observer;
|
observers.frame_count_observer = frame_count_observer;
|
||||||
observers.rtcp_type_observer = rtcp_type_observer;
|
observers.rtcp_type_observer = rtcp_type_observer;
|
||||||
observers.send_delay_observer = send_delay_observer;
|
|
||||||
observers.send_packet_observer = nullptr;
|
observers.send_packet_observer = nullptr;
|
||||||
return observers;
|
return observers;
|
||||||
}
|
}
|
||||||
@ -145,8 +143,7 @@ class RtpVideoSenderTestFixture {
|
|||||||
time_controller_.GetClock(), suspended_ssrcs, suspended_payload_states,
|
time_controller_.GetClock(), suspended_ssrcs, suspended_payload_states,
|
||||||
config_.rtp, config_.rtcp_report_interval_ms, &transport_,
|
config_.rtp, config_.rtcp_report_interval_ms, &transport_,
|
||||||
CreateObservers(&encoder_feedback_, &stats_proxy_, &stats_proxy_,
|
CreateObservers(&encoder_feedback_, &stats_proxy_, &stats_proxy_,
|
||||||
&stats_proxy_, frame_count_observer, &stats_proxy_,
|
&stats_proxy_, frame_count_observer, &stats_proxy_),
|
||||||
&stats_proxy_),
|
|
||||||
&transport_controller_, &event_log_, &retransmission_rate_limiter_,
|
&transport_controller_, &event_log_, &retransmission_rate_limiter_,
|
||||||
std::make_unique<FecControllerDefault>(time_controller_.GetClock()),
|
std::make_unique<FecControllerDefault>(time_controller_.GetClock()),
|
||||||
nullptr, CryptoOptions{}, frame_transformer,
|
nullptr, CryptoOptions{}, frame_transformer,
|
||||||
|
|||||||
@ -406,19 +406,8 @@ class BitrateStatisticsObserver {
|
|||||||
uint32_t ssrc) = 0;
|
uint32_t ssrc) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Callback, used to notify an observer whenever the send-side delay is updated.
|
|
||||||
class SendSideDelayObserver {
|
|
||||||
public:
|
|
||||||
virtual ~SendSideDelayObserver() {}
|
|
||||||
virtual void SendSideDelayUpdated(int avg_delay_ms,
|
|
||||||
int max_delay_ms,
|
|
||||||
uint32_t ssrc) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Callback, used to notify an observer whenever a packet is sent to the
|
// Callback, used to notify an observer whenever a packet is sent to the
|
||||||
// transport.
|
// transport.
|
||||||
// TODO(asapersson): This class will remove the need for SendSideDelayObserver.
|
|
||||||
// Remove SendSideDelayObserver once possible.
|
|
||||||
class SendPacketObserver {
|
class SendPacketObserver {
|
||||||
public:
|
public:
|
||||||
virtual ~SendPacketObserver() = default;
|
virtual ~SendPacketObserver() = default;
|
||||||
|
|||||||
@ -23,7 +23,6 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace {
|
namespace {
|
||||||
constexpr uint32_t kTimestampTicksPerMs = 90;
|
constexpr uint32_t kTimestampTicksPerMs = 90;
|
||||||
constexpr int kSendSideDelayWindowMs = 1000;
|
|
||||||
constexpr TimeDelta kBitrateStatisticsWindow = TimeDelta::Seconds(1);
|
constexpr TimeDelta kBitrateStatisticsWindow = TimeDelta::Seconds(1);
|
||||||
constexpr size_t kRtpSequenceNumberMapMaxEntries = 1 << 13;
|
constexpr size_t kRtpSequenceNumberMapMaxEntries = 1 << 13;
|
||||||
|
|
||||||
@ -73,15 +72,12 @@ DEPRECATED_RtpSenderEgress::DEPRECATED_RtpSenderEgress(
|
|||||||
is_audio_(config.audio),
|
is_audio_(config.audio),
|
||||||
need_rtp_packet_infos_(config.need_rtp_packet_infos),
|
need_rtp_packet_infos_(config.need_rtp_packet_infos),
|
||||||
transport_feedback_observer_(config.transport_feedback_callback),
|
transport_feedback_observer_(config.transport_feedback_callback),
|
||||||
send_side_delay_observer_(config.send_side_delay_observer),
|
|
||||||
send_packet_observer_(config.send_packet_observer),
|
send_packet_observer_(config.send_packet_observer),
|
||||||
rtp_stats_callback_(config.rtp_stats_callback),
|
rtp_stats_callback_(config.rtp_stats_callback),
|
||||||
bitrate_callback_(config.send_bitrate_observer),
|
bitrate_callback_(config.send_bitrate_observer),
|
||||||
media_has_been_sent_(false),
|
media_has_been_sent_(false),
|
||||||
force_part_of_allocation_(false),
|
force_part_of_allocation_(false),
|
||||||
timestamp_offset_(0),
|
timestamp_offset_(0),
|
||||||
max_delay_it_(send_delays_.end()),
|
|
||||||
sum_delays_ms_(0),
|
|
||||||
send_rates_(kNumMediaTypes, BitrateTracker(kBitrateStatisticsWindow)),
|
send_rates_(kNumMediaTypes, BitrateTracker(kBitrateStatisticsWindow)),
|
||||||
rtp_sequence_number_map_(need_rtp_packet_infos_
|
rtp_sequence_number_map_(need_rtp_packet_infos_
|
||||||
? std::make_unique<RtpSequenceNumberMap>(
|
? std::make_unique<RtpSequenceNumberMap>(
|
||||||
@ -180,7 +176,6 @@ void DEPRECATED_RtpSenderEgress::SendPacket(
|
|||||||
|
|
||||||
if (packet->packet_type() != RtpPacketMediaType::kPadding &&
|
if (packet->packet_type() != RtpPacketMediaType::kPadding &&
|
||||||
packet->packet_type() != RtpPacketMediaType::kRetransmission) {
|
packet->packet_type() != RtpPacketMediaType::kRetransmission) {
|
||||||
UpdateDelayStatistics(packet->capture_time().ms(), now_ms, packet_ssrc);
|
|
||||||
UpdateOnSendPacket(options.packet_id, packet->capture_time().ms(),
|
UpdateOnSendPacket(options.packet_id, packet->capture_time().ms(),
|
||||||
packet_ssrc);
|
packet_ssrc);
|
||||||
}
|
}
|
||||||
@ -317,88 +312,6 @@ void DEPRECATED_RtpSenderEgress::AddPacketToTransportFeedback(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DEPRECATED_RtpSenderEgress::UpdateDelayStatistics(int64_t capture_time_ms,
|
|
||||||
int64_t now_ms,
|
|
||||||
uint32_t ssrc) {
|
|
||||||
if (!send_side_delay_observer_ || capture_time_ms <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int avg_delay_ms = 0;
|
|
||||||
int max_delay_ms = 0;
|
|
||||||
{
|
|
||||||
MutexLock lock(&lock_);
|
|
||||||
// Compute the max and average of the recent capture-to-send delays.
|
|
||||||
// The time complexity of the current approach depends on the distribution
|
|
||||||
// of the delay values. This could be done more efficiently.
|
|
||||||
|
|
||||||
// Remove elements older than kSendSideDelayWindowMs.
|
|
||||||
auto lower_bound =
|
|
||||||
send_delays_.lower_bound(now_ms - kSendSideDelayWindowMs);
|
|
||||||
for (auto it = send_delays_.begin(); it != lower_bound; ++it) {
|
|
||||||
if (max_delay_it_ == it) {
|
|
||||||
max_delay_it_ = send_delays_.end();
|
|
||||||
}
|
|
||||||
sum_delays_ms_ -= it->second;
|
|
||||||
}
|
|
||||||
send_delays_.erase(send_delays_.begin(), lower_bound);
|
|
||||||
if (max_delay_it_ == send_delays_.end()) {
|
|
||||||
// Removed the previous max. Need to recompute.
|
|
||||||
RecomputeMaxSendDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the new element.
|
|
||||||
RTC_DCHECK_GE(now_ms, 0);
|
|
||||||
RTC_DCHECK_LE(now_ms, std::numeric_limits<int64_t>::max() / 2);
|
|
||||||
RTC_DCHECK_GE(capture_time_ms, 0);
|
|
||||||
RTC_DCHECK_LE(capture_time_ms, std::numeric_limits<int64_t>::max() / 2);
|
|
||||||
int64_t diff_ms = now_ms - capture_time_ms;
|
|
||||||
RTC_DCHECK_GE(diff_ms, static_cast<int64_t>(0));
|
|
||||||
RTC_DCHECK_LE(diff_ms, std::numeric_limits<int>::max());
|
|
||||||
int new_send_delay = rtc::dchecked_cast<int>(now_ms - capture_time_ms);
|
|
||||||
SendDelayMap::iterator it;
|
|
||||||
bool inserted;
|
|
||||||
std::tie(it, inserted) =
|
|
||||||
send_delays_.insert(std::make_pair(now_ms, new_send_delay));
|
|
||||||
if (!inserted) {
|
|
||||||
// TODO(terelius): If we have multiple delay measurements during the same
|
|
||||||
// millisecond then we keep the most recent one. It is not clear that this
|
|
||||||
// is the right decision, but it preserves an earlier behavior.
|
|
||||||
int previous_send_delay = it->second;
|
|
||||||
sum_delays_ms_ -= previous_send_delay;
|
|
||||||
it->second = new_send_delay;
|
|
||||||
if (max_delay_it_ == it && new_send_delay < previous_send_delay) {
|
|
||||||
RecomputeMaxSendDelay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (max_delay_it_ == send_delays_.end() ||
|
|
||||||
it->second >= max_delay_it_->second) {
|
|
||||||
max_delay_it_ = it;
|
|
||||||
}
|
|
||||||
sum_delays_ms_ += new_send_delay;
|
|
||||||
|
|
||||||
size_t num_delays = send_delays_.size();
|
|
||||||
RTC_DCHECK(max_delay_it_ != send_delays_.end());
|
|
||||||
max_delay_ms = rtc::dchecked_cast<int>(max_delay_it_->second);
|
|
||||||
int64_t avg_ms = (sum_delays_ms_ + num_delays / 2) / num_delays;
|
|
||||||
RTC_DCHECK_GE(avg_ms, static_cast<int64_t>(0));
|
|
||||||
RTC_DCHECK_LE(avg_ms,
|
|
||||||
static_cast<int64_t>(std::numeric_limits<int>::max()));
|
|
||||||
avg_delay_ms =
|
|
||||||
rtc::dchecked_cast<int>((sum_delays_ms_ + num_delays / 2) / num_delays);
|
|
||||||
}
|
|
||||||
send_side_delay_observer_->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
|
|
||||||
ssrc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DEPRECATED_RtpSenderEgress::RecomputeMaxSendDelay() {
|
|
||||||
max_delay_it_ = send_delays_.begin();
|
|
||||||
for (auto it = send_delays_.begin(); it != send_delays_.end(); ++it) {
|
|
||||||
if (it->second >= max_delay_it_->second) {
|
|
||||||
max_delay_it_ = it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DEPRECATED_RtpSenderEgress::UpdateOnSendPacket(int packet_id,
|
void DEPRECATED_RtpSenderEgress::UpdateOnSendPacket(int packet_id,
|
||||||
int64_t capture_time_ms,
|
int64_t capture_time_ms,
|
||||||
uint32_t ssrc) {
|
uint32_t ssrc) {
|
||||||
|
|||||||
@ -83,20 +83,11 @@ class DEPRECATED_RtpSenderEgress {
|
|||||||
RTC_LOCKS_EXCLUDED(lock_);
|
RTC_LOCKS_EXCLUDED(lock_);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Maps capture time in milliseconds to send-side delay in milliseconds.
|
|
||||||
// Send-side delay is the difference between transmission time and capture
|
|
||||||
// time.
|
|
||||||
typedef std::map<int64_t, int> SendDelayMap;
|
|
||||||
|
|
||||||
RtpSendRates GetSendRatesLocked() const RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
RtpSendRates GetSendRatesLocked() const RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||||
bool HasCorrectSsrc(const RtpPacketToSend& packet) const;
|
bool HasCorrectSsrc(const RtpPacketToSend& packet) const;
|
||||||
void AddPacketToTransportFeedback(uint16_t packet_id,
|
void AddPacketToTransportFeedback(uint16_t packet_id,
|
||||||
const RtpPacketToSend& packet,
|
const RtpPacketToSend& packet,
|
||||||
const PacedPacketInfo& pacing_info);
|
const PacedPacketInfo& pacing_info);
|
||||||
void UpdateDelayStatistics(int64_t capture_time_ms,
|
|
||||||
int64_t now_ms,
|
|
||||||
uint32_t ssrc);
|
|
||||||
void RecomputeMaxSendDelay() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
|
||||||
void UpdateOnSendPacket(int packet_id,
|
void UpdateOnSendPacket(int packet_id,
|
||||||
int64_t capture_time_ms,
|
int64_t capture_time_ms,
|
||||||
uint32_t ssrc);
|
uint32_t ssrc);
|
||||||
@ -119,7 +110,6 @@ class DEPRECATED_RtpSenderEgress {
|
|||||||
const bool need_rtp_packet_infos_;
|
const bool need_rtp_packet_infos_;
|
||||||
|
|
||||||
TransportFeedbackObserver* const transport_feedback_observer_;
|
TransportFeedbackObserver* const transport_feedback_observer_;
|
||||||
SendSideDelayObserver* const send_side_delay_observer_;
|
|
||||||
SendPacketObserver* const send_packet_observer_;
|
SendPacketObserver* const send_packet_observer_;
|
||||||
StreamDataCountersCallback* const rtp_stats_callback_;
|
StreamDataCountersCallback* const rtp_stats_callback_;
|
||||||
BitrateStatisticsObserver* const bitrate_callback_;
|
BitrateStatisticsObserver* const bitrate_callback_;
|
||||||
@ -129,10 +119,6 @@ class DEPRECATED_RtpSenderEgress {
|
|||||||
bool force_part_of_allocation_ RTC_GUARDED_BY(lock_);
|
bool force_part_of_allocation_ RTC_GUARDED_BY(lock_);
|
||||||
uint32_t timestamp_offset_ RTC_GUARDED_BY(lock_);
|
uint32_t timestamp_offset_ RTC_GUARDED_BY(lock_);
|
||||||
|
|
||||||
SendDelayMap send_delays_ RTC_GUARDED_BY(lock_);
|
|
||||||
SendDelayMap::const_iterator max_delay_it_ RTC_GUARDED_BY(lock_);
|
|
||||||
// The sum of delays over a kSendSideDelayWindowMs sliding window.
|
|
||||||
int64_t sum_delays_ms_ RTC_GUARDED_BY(lock_);
|
|
||||||
StreamDataCounters rtp_stats_ RTC_GUARDED_BY(lock_);
|
StreamDataCounters rtp_stats_ RTC_GUARDED_BY(lock_);
|
||||||
StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(lock_);
|
StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(lock_);
|
||||||
// One element per value in RtpPacketMediaType, with index matching value.
|
// One element per value in RtpPacketMediaType, with index matching value.
|
||||||
|
|||||||
@ -95,7 +95,6 @@ class RtpRtcpInterface : public RtcpFeedbackSenderInterface {
|
|||||||
VideoFecGenerator* fec_generator = nullptr;
|
VideoFecGenerator* fec_generator = nullptr;
|
||||||
|
|
||||||
BitrateStatisticsObserver* send_bitrate_observer = nullptr;
|
BitrateStatisticsObserver* send_bitrate_observer = nullptr;
|
||||||
SendSideDelayObserver* send_side_delay_observer = nullptr;
|
|
||||||
RtcEventLog* event_log = nullptr;
|
RtcEventLog* event_log = nullptr;
|
||||||
SendPacketObserver* send_packet_observer = nullptr;
|
SendPacketObserver* send_packet_observer = nullptr;
|
||||||
RateLimiter* retransmission_rate_limiter = nullptr;
|
RateLimiter* retransmission_rate_limiter = nullptr;
|
||||||
|
|||||||
@ -23,7 +23,6 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace {
|
namespace {
|
||||||
constexpr uint32_t kTimestampTicksPerMs = 90;
|
constexpr uint32_t kTimestampTicksPerMs = 90;
|
||||||
constexpr TimeDelta kSendSideDelayWindow = TimeDelta::Seconds(1);
|
|
||||||
constexpr TimeDelta kBitrateStatisticsWindow = TimeDelta::Seconds(1);
|
constexpr TimeDelta kBitrateStatisticsWindow = TimeDelta::Seconds(1);
|
||||||
constexpr size_t kRtpSequenceNumberMapMaxEntries = 1 << 13;
|
constexpr size_t kRtpSequenceNumberMapMaxEntries = 1 << 13;
|
||||||
constexpr TimeDelta kUpdateInterval = kBitrateStatisticsWindow;
|
constexpr TimeDelta kUpdateInterval = kBitrateStatisticsWindow;
|
||||||
@ -96,15 +95,12 @@ RtpSenderEgress::RtpSenderEgress(const RtpRtcpInterface::Configuration& config,
|
|||||||
need_rtp_packet_infos_(config.need_rtp_packet_infos),
|
need_rtp_packet_infos_(config.need_rtp_packet_infos),
|
||||||
fec_generator_(config.fec_generator),
|
fec_generator_(config.fec_generator),
|
||||||
transport_feedback_observer_(config.transport_feedback_callback),
|
transport_feedback_observer_(config.transport_feedback_callback),
|
||||||
send_side_delay_observer_(config.send_side_delay_observer),
|
|
||||||
send_packet_observer_(config.send_packet_observer),
|
send_packet_observer_(config.send_packet_observer),
|
||||||
rtp_stats_callback_(config.rtp_stats_callback),
|
rtp_stats_callback_(config.rtp_stats_callback),
|
||||||
bitrate_callback_(config.send_bitrate_observer),
|
bitrate_callback_(config.send_bitrate_observer),
|
||||||
media_has_been_sent_(false),
|
media_has_been_sent_(false),
|
||||||
force_part_of_allocation_(false),
|
force_part_of_allocation_(false),
|
||||||
timestamp_offset_(0),
|
timestamp_offset_(0),
|
||||||
max_delay_it_(send_delays_.end()),
|
|
||||||
sum_delays_(TimeDelta::Zero()),
|
|
||||||
send_rates_(kNumMediaTypes, BitrateTracker(kBitrateStatisticsWindow)),
|
send_rates_(kNumMediaTypes, BitrateTracker(kBitrateStatisticsWindow)),
|
||||||
rtp_sequence_number_map_(need_rtp_packet_infos_
|
rtp_sequence_number_map_(need_rtp_packet_infos_
|
||||||
? std::make_unique<RtpSequenceNumberMap>(
|
? std::make_unique<RtpSequenceNumberMap>(
|
||||||
@ -263,11 +259,11 @@ void RtpSenderEgress::CompleteSendPacket(const Packet& compound_packet,
|
|||||||
|
|
||||||
options.additional_data = packet->additional_data();
|
options.additional_data = packet->additional_data();
|
||||||
|
|
||||||
const uint32_t packet_ssrc = packet->Ssrc();
|
|
||||||
if (packet->packet_type() != RtpPacketMediaType::kPadding &&
|
if (packet->packet_type() != RtpPacketMediaType::kPadding &&
|
||||||
packet->packet_type() != RtpPacketMediaType::kRetransmission) {
|
packet->packet_type() != RtpPacketMediaType::kRetransmission &&
|
||||||
UpdateDelayStatistics(packet->capture_time(), now, packet_ssrc);
|
send_packet_observer_ != nullptr && packet->capture_time().IsFinite()) {
|
||||||
UpdateOnSendPacket(packet_id, packet->capture_time(), packet_ssrc);
|
send_packet_observer_->OnSendPacket(packet_id, packet->capture_time(),
|
||||||
|
packet->Ssrc());
|
||||||
}
|
}
|
||||||
options.batchable = enable_send_packet_batching_ && !is_audio_;
|
options.batchable = enable_send_packet_batching_ && !is_audio_;
|
||||||
options.last_packet_in_batch = last_in_batch;
|
options.last_packet_in_batch = last_in_batch;
|
||||||
@ -294,8 +290,8 @@ void RtpSenderEgress::CompleteSendPacket(const Packet& compound_packet,
|
|||||||
RTC_DCHECK(packet->packet_type().has_value());
|
RTC_DCHECK(packet->packet_type().has_value());
|
||||||
RtpPacketMediaType packet_type = *packet->packet_type();
|
RtpPacketMediaType packet_type = *packet->packet_type();
|
||||||
RtpPacketCounter counter(*packet);
|
RtpPacketCounter counter(*packet);
|
||||||
size_t size = packet->size();
|
UpdateRtpStats(now, packet->Ssrc(), packet_type, std::move(counter),
|
||||||
UpdateRtpStats(now, packet_ssrc, packet_type, std::move(counter), size);
|
packet->size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,83 +437,6 @@ void RtpSenderEgress::AddPacketToTransportFeedback(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpSenderEgress::UpdateDelayStatistics(Timestamp capture_time,
|
|
||||||
Timestamp now,
|
|
||||||
uint32_t ssrc) {
|
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
|
||||||
if (!send_side_delay_observer_ || capture_time.IsInfinite())
|
|
||||||
return;
|
|
||||||
|
|
||||||
TimeDelta avg_delay = TimeDelta::Zero();
|
|
||||||
TimeDelta max_delay = TimeDelta::Zero();
|
|
||||||
{
|
|
||||||
// Compute the max and average of the recent capture-to-send delays.
|
|
||||||
// The time complexity of the current approach depends on the distribution
|
|
||||||
// of the delay values. This could be done more efficiently.
|
|
||||||
|
|
||||||
// Remove elements older than kSendSideDelayWindowMs.
|
|
||||||
auto lower_bound = send_delays_.lower_bound(now - kSendSideDelayWindow);
|
|
||||||
for (auto it = send_delays_.begin(); it != lower_bound; ++it) {
|
|
||||||
if (max_delay_it_ == it) {
|
|
||||||
max_delay_it_ = send_delays_.end();
|
|
||||||
}
|
|
||||||
sum_delays_ -= it->second;
|
|
||||||
}
|
|
||||||
send_delays_.erase(send_delays_.begin(), lower_bound);
|
|
||||||
if (max_delay_it_ == send_delays_.end()) {
|
|
||||||
// Removed the previous max. Need to recompute.
|
|
||||||
RecomputeMaxSendDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the new element.
|
|
||||||
TimeDelta new_send_delay = now - capture_time;
|
|
||||||
auto [it, inserted] = send_delays_.emplace(now, new_send_delay);
|
|
||||||
if (!inserted) {
|
|
||||||
// TODO(terelius): If we have multiple delay measurements during the same
|
|
||||||
// millisecond then we keep the most recent one. It is not clear that this
|
|
||||||
// is the right decision, but it preserves an earlier behavior.
|
|
||||||
TimeDelta previous_send_delay = it->second;
|
|
||||||
sum_delays_ -= previous_send_delay;
|
|
||||||
it->second = new_send_delay;
|
|
||||||
if (max_delay_it_ == it && new_send_delay < previous_send_delay) {
|
|
||||||
RecomputeMaxSendDelay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (max_delay_it_ == send_delays_.end() ||
|
|
||||||
it->second >= max_delay_it_->second) {
|
|
||||||
max_delay_it_ = it;
|
|
||||||
}
|
|
||||||
sum_delays_ += new_send_delay;
|
|
||||||
|
|
||||||
size_t num_delays = send_delays_.size();
|
|
||||||
RTC_DCHECK(max_delay_it_ != send_delays_.end());
|
|
||||||
max_delay = max_delay_it_->second;
|
|
||||||
avg_delay = sum_delays_ / num_delays;
|
|
||||||
}
|
|
||||||
send_side_delay_observer_->SendSideDelayUpdated(avg_delay.ms(),
|
|
||||||
max_delay.ms(), ssrc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtpSenderEgress::RecomputeMaxSendDelay() {
|
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
|
||||||
max_delay_it_ = send_delays_.begin();
|
|
||||||
for (auto it = send_delays_.begin(); it != send_delays_.end(); ++it) {
|
|
||||||
if (it->second >= max_delay_it_->second) {
|
|
||||||
max_delay_it_ = it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtpSenderEgress::UpdateOnSendPacket(absl::optional<uint16_t> packet_id,
|
|
||||||
Timestamp capture_time,
|
|
||||||
uint32_t ssrc) {
|
|
||||||
if (!send_packet_observer_ || capture_time.IsInfinite()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_packet_observer_->OnSendPacket(packet_id, capture_time, ssrc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RtpSenderEgress::SendPacketToNetwork(const RtpPacketToSend& packet,
|
bool RtpSenderEgress::SendPacketToNetwork(const RtpPacketToSend& packet,
|
||||||
const PacketOptions& options,
|
const PacketOptions& options,
|
||||||
const PacedPacketInfo& pacing_info) {
|
const PacedPacketInfo& pacing_info) {
|
||||||
|
|||||||
@ -113,13 +113,7 @@ class RtpSenderEgress {
|
|||||||
void AddPacketToTransportFeedback(uint16_t packet_id,
|
void AddPacketToTransportFeedback(uint16_t packet_id,
|
||||||
const RtpPacketToSend& packet,
|
const RtpPacketToSend& packet,
|
||||||
const PacedPacketInfo& pacing_info);
|
const PacedPacketInfo& pacing_info);
|
||||||
void UpdateDelayStatistics(Timestamp capture_time,
|
|
||||||
Timestamp now,
|
|
||||||
uint32_t ssrc);
|
|
||||||
void RecomputeMaxSendDelay();
|
|
||||||
void UpdateOnSendPacket(absl::optional<uint16_t> packet_id,
|
|
||||||
Timestamp capture_time,
|
|
||||||
uint32_t ssrc);
|
|
||||||
// Sends packet on to `transport_`, leaving the RTP module.
|
// Sends packet on to `transport_`, leaving the RTP module.
|
||||||
bool SendPacketToNetwork(const RtpPacketToSend& packet,
|
bool SendPacketToNetwork(const RtpPacketToSend& packet,
|
||||||
const PacketOptions& options,
|
const PacketOptions& options,
|
||||||
@ -153,7 +147,6 @@ class RtpSenderEgress {
|
|||||||
absl::optional<uint16_t> last_sent_rtx_seq_ RTC_GUARDED_BY(worker_queue_);
|
absl::optional<uint16_t> last_sent_rtx_seq_ RTC_GUARDED_BY(worker_queue_);
|
||||||
|
|
||||||
TransportFeedbackObserver* const transport_feedback_observer_;
|
TransportFeedbackObserver* const transport_feedback_observer_;
|
||||||
SendSideDelayObserver* const send_side_delay_observer_;
|
|
||||||
SendPacketObserver* const send_packet_observer_;
|
SendPacketObserver* const send_packet_observer_;
|
||||||
StreamDataCountersCallback* const rtp_stats_callback_;
|
StreamDataCountersCallback* const rtp_stats_callback_;
|
||||||
BitrateStatisticsObserver* const bitrate_callback_;
|
BitrateStatisticsObserver* const bitrate_callback_;
|
||||||
@ -162,13 +155,6 @@ class RtpSenderEgress {
|
|||||||
bool force_part_of_allocation_ RTC_GUARDED_BY(worker_queue_);
|
bool force_part_of_allocation_ RTC_GUARDED_BY(worker_queue_);
|
||||||
uint32_t timestamp_offset_ RTC_GUARDED_BY(worker_queue_);
|
uint32_t timestamp_offset_ RTC_GUARDED_BY(worker_queue_);
|
||||||
|
|
||||||
// Maps capture time to send-side delay. Send-side delay is the difference
|
|
||||||
// between transmission time and capture time.
|
|
||||||
std::map<Timestamp, TimeDelta> send_delays_ RTC_GUARDED_BY(worker_queue_);
|
|
||||||
std::map<Timestamp, TimeDelta>::const_iterator max_delay_it_
|
|
||||||
RTC_GUARDED_BY(worker_queue_);
|
|
||||||
// The sum of delays over a kSendSideDelayWindowMs sliding window.
|
|
||||||
TimeDelta sum_delays_ RTC_GUARDED_BY(worker_queue_);
|
|
||||||
StreamDataCounters rtp_stats_ RTC_GUARDED_BY(worker_queue_);
|
StreamDataCounters rtp_stats_ RTC_GUARDED_BY(worker_queue_);
|
||||||
StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(worker_queue_);
|
StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(worker_queue_);
|
||||||
// One element per value in RtpPacketMediaType, with index matching value.
|
// One element per value in RtpPacketMediaType, with index matching value.
|
||||||
|
|||||||
@ -77,11 +77,6 @@ class MockStreamDataCountersCallback : public StreamDataCountersCallback {
|
|||||||
(override));
|
(override));
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockSendSideDelayObserver : public SendSideDelayObserver {
|
|
||||||
public:
|
|
||||||
MOCK_METHOD(void, SendSideDelayUpdated, (int, int, uint32_t), (override));
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TransmittedPacket {
|
struct TransmittedPacket {
|
||||||
TransmittedPacket(rtc::ArrayView<const uint8_t> data,
|
TransmittedPacket(rtc::ArrayView<const uint8_t> data,
|
||||||
const PacketOptions& packet_options,
|
const PacketOptions& packet_options,
|
||||||
@ -329,48 +324,6 @@ TEST_F(RtpSenderEgressTest,
|
|||||||
EXPECT_EQ(offset, 0);
|
EXPECT_EQ(offset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RtpSenderEgressTest, OnSendSideDelayUpdated) {
|
|
||||||
StrictMock<MockSendSideDelayObserver> send_side_delay_observer;
|
|
||||||
RtpRtcpInterface::Configuration config = DefaultConfig();
|
|
||||||
config.send_side_delay_observer = &send_side_delay_observer;
|
|
||||||
auto sender = std::make_unique<RtpSenderEgress>(config, &packet_history_);
|
|
||||||
|
|
||||||
// Send packet with 10 ms send-side delay. The average, max and total should
|
|
||||||
// be 10 ms.
|
|
||||||
EXPECT_CALL(send_side_delay_observer, SendSideDelayUpdated(10, 10, kSsrc));
|
|
||||||
int64_t capture_time_ms = clock_->TimeInMilliseconds();
|
|
||||||
time_controller_.AdvanceTime(TimeDelta::Millis(10));
|
|
||||||
sender->SendPacket(BuildRtpPacket(/*marker=*/true, capture_time_ms),
|
|
||||||
PacedPacketInfo());
|
|
||||||
|
|
||||||
// Send another packet with 20 ms delay. The average, max and total should be
|
|
||||||
// 15, 20 and 30 ms respectively.
|
|
||||||
EXPECT_CALL(send_side_delay_observer, SendSideDelayUpdated(15, 20, kSsrc));
|
|
||||||
capture_time_ms = clock_->TimeInMilliseconds();
|
|
||||||
time_controller_.AdvanceTime(TimeDelta::Millis(20));
|
|
||||||
sender->SendPacket(BuildRtpPacket(/*marker=*/true, capture_time_ms),
|
|
||||||
PacedPacketInfo());
|
|
||||||
|
|
||||||
// Send another packet at the same time, which replaces the last packet.
|
|
||||||
// Since this packet has 0 ms delay, the average is now 5 ms and max is 10 ms.
|
|
||||||
// The total counter stays the same though.
|
|
||||||
// TODO(terelius): Is is not clear that this is the right behavior.
|
|
||||||
EXPECT_CALL(send_side_delay_observer, SendSideDelayUpdated(5, 10, kSsrc));
|
|
||||||
capture_time_ms = clock_->TimeInMilliseconds();
|
|
||||||
sender->SendPacket(BuildRtpPacket(/*marker=*/true, capture_time_ms),
|
|
||||||
PacedPacketInfo());
|
|
||||||
|
|
||||||
// Send a packet 1 second later. The earlier packets should have timed
|
|
||||||
// out, so both max and average should be the delay of this packet. The total
|
|
||||||
// keeps increasing.
|
|
||||||
time_controller_.AdvanceTime(TimeDelta::Seconds(1));
|
|
||||||
EXPECT_CALL(send_side_delay_observer, SendSideDelayUpdated(1, 1, kSsrc));
|
|
||||||
capture_time_ms = clock_->TimeInMilliseconds();
|
|
||||||
time_controller_.AdvanceTime(TimeDelta::Millis(1));
|
|
||||||
sender->SendPacket(BuildRtpPacket(/*marker=*/true, capture_time_ms),
|
|
||||||
PacedPacketInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(RtpSenderEgressTest, WritesPacerExitToTimingExtension) {
|
TEST_F(RtpSenderEgressTest, WritesPacerExitToTimingExtension) {
|
||||||
std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
|
std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
|
||||||
header_extensions_.RegisterByUri(kVideoTimingExtensionId,
|
header_extensions_.RegisterByUri(kVideoTimingExtensionId,
|
||||||
@ -852,7 +805,6 @@ TEST_F(RtpSenderEgressTest, SendPacketSetsPacketOptions) {
|
|||||||
|
|
||||||
TEST_F(RtpSenderEgressTest, SendPacketUpdatesStats) {
|
TEST_F(RtpSenderEgressTest, SendPacketUpdatesStats) {
|
||||||
const size_t kPayloadSize = 1000;
|
const size_t kPayloadSize = 1000;
|
||||||
StrictMock<MockSendSideDelayObserver> send_side_delay_observer;
|
|
||||||
|
|
||||||
const rtc::ArrayView<const RtpExtensionSize> kNoRtpHeaderExtensionSizes;
|
const rtc::ArrayView<const RtpExtensionSize> kNoRtpHeaderExtensionSizes;
|
||||||
FlexfecSender flexfec(kFlexfectPayloadType, kFlexFecSsrc, kSsrc, /*mid=*/"",
|
FlexfecSender flexfec(kFlexfectPayloadType, kFlexFecSsrc, kSsrc, /*mid=*/"",
|
||||||
@ -860,7 +812,6 @@ TEST_F(RtpSenderEgressTest, SendPacketUpdatesStats) {
|
|||||||
/*rtp_state=*/nullptr, time_controller_.GetClock());
|
/*rtp_state=*/nullptr, time_controller_.GetClock());
|
||||||
RtpRtcpInterface::Configuration config = DefaultConfig();
|
RtpRtcpInterface::Configuration config = DefaultConfig();
|
||||||
config.fec_generator = &flexfec;
|
config.fec_generator = &flexfec;
|
||||||
config.send_side_delay_observer = &send_side_delay_observer;
|
|
||||||
auto sender = std::make_unique<RtpSenderEgress>(config, &packet_history_);
|
auto sender = std::make_unique<RtpSenderEgress>(config, &packet_history_);
|
||||||
|
|
||||||
header_extensions_.RegisterByUri(kTransportSequenceNumberExtensionId,
|
header_extensions_.RegisterByUri(kTransportSequenceNumberExtensionId,
|
||||||
@ -889,11 +840,6 @@ TEST_F(RtpSenderEgressTest, SendPacketUpdatesStats) {
|
|||||||
const int64_t kDiffMs = 25;
|
const int64_t kDiffMs = 25;
|
||||||
time_controller_.AdvanceTime(TimeDelta::Millis(kDiffMs));
|
time_controller_.AdvanceTime(TimeDelta::Millis(kDiffMs));
|
||||||
|
|
||||||
EXPECT_CALL(send_side_delay_observer,
|
|
||||||
SendSideDelayUpdated(kDiffMs, kDiffMs, kSsrc));
|
|
||||||
EXPECT_CALL(send_side_delay_observer,
|
|
||||||
SendSideDelayUpdated(kDiffMs, kDiffMs, kFlexFecSsrc));
|
|
||||||
|
|
||||||
EXPECT_CALL(send_packet_observer_, OnSendPacket(Eq(1), capture_time, kSsrc));
|
EXPECT_CALL(send_packet_observer_, OnSendPacket(Eq(1), capture_time, kSsrc));
|
||||||
|
|
||||||
sender->SendPacket(std::move(video_packet), PacedPacketInfo());
|
sender->SendPacket(std::move(video_packet), PacedPacketInfo());
|
||||||
|
|||||||
@ -43,8 +43,7 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
|
|||||||
public RtcpPacketTypeCounterObserver,
|
public RtcpPacketTypeCounterObserver,
|
||||||
public StreamDataCountersCallback,
|
public StreamDataCountersCallback,
|
||||||
public BitrateStatisticsObserver,
|
public BitrateStatisticsObserver,
|
||||||
public FrameCountObserver,
|
public FrameCountObserver {
|
||||||
public SendSideDelayObserver {
|
|
||||||
public:
|
public:
|
||||||
static constexpr TimeDelta kStatsTimeout = TimeDelta::Seconds(5);
|
static constexpr TimeDelta kStatsTimeout = TimeDelta::Seconds(5);
|
||||||
// Number of required samples to be collected before a metric is added
|
// Number of required samples to be collected before a metric is added
|
||||||
@ -129,11 +128,6 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
|
|||||||
void FrameCountUpdated(const FrameCounts& frame_counts,
|
void FrameCountUpdated(const FrameCounts& frame_counts,
|
||||||
uint32_t ssrc) override;
|
uint32_t ssrc) override;
|
||||||
|
|
||||||
// From SendSideDelayObserver.
|
|
||||||
void SendSideDelayUpdated(int avg_delay_ms,
|
|
||||||
int max_delay_ms,
|
|
||||||
uint32_t ssrc) override {}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class SampleCounter {
|
class SampleCounter {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -101,7 +101,6 @@ RtpSenderObservers CreateObservers(RtcpRttStats* call_stats,
|
|||||||
observers.bitrate_observer = stats_proxy;
|
observers.bitrate_observer = stats_proxy;
|
||||||
observers.frame_count_observer = stats_proxy;
|
observers.frame_count_observer = stats_proxy;
|
||||||
observers.rtcp_type_observer = stats_proxy;
|
observers.rtcp_type_observer = stats_proxy;
|
||||||
observers.send_delay_observer = nullptr;
|
|
||||||
observers.send_packet_observer = send_packet_observer;
|
observers.send_packet_observer = send_packet_observer;
|
||||||
return observers;
|
return observers;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user