mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-16 15:20:42 +01:00

Split out from https://webrtc-review.googlesource.com/c/src/+/173708 This CL enables FEC packets to be generated as media packets are sent, rather than generated, i.e. media packets are inserted into the fec generator after the pacing stage rather than at packetization time. This may have some small impact of performance. FEC packets are typically only generated when a new packet with a marker bit is added, which means FEC packets protecting a frame will now be sent after all of the media packets, rather than (potentially) interleaved with them. Therefore this feature is currently behind a flag so we can examine the impact. Once we are comfortable with the behavior we'll make it default and remove the old code. Note that this change does not include the "protect all header extensions" part of the original CL - that will be a follow-up. Bug: webrtc:11340 Change-Id: I3fe139c5d53968579b75b91e2612075451ff0f5d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/177760 Commit-Queue: Erik Språng <sprang@webrtc.org> Reviewed-by: Sebastian Jansson <srte@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31558}
239 lines
8.7 KiB
C++
239 lines
8.7 KiB
C++
/*
|
|
* Copyright (c) 2019 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.
|
|
*/
|
|
|
|
#ifndef MODULES_PACING_PACING_CONTROLLER_H_
|
|
#define MODULES_PACING_PACING_CONTROLLER_H_
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include <atomic>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/function_view.h"
|
|
#include "api/rtc_event_log/rtc_event_log.h"
|
|
#include "api/transport/field_trial_based_config.h"
|
|
#include "api/transport/network_types.h"
|
|
#include "api/transport/webrtc_key_value_config.h"
|
|
#include "modules/pacing/bitrate_prober.h"
|
|
#include "modules/pacing/interval_budget.h"
|
|
#include "modules/pacing/round_robin_packet_queue.h"
|
|
#include "modules/pacing/rtp_packet_pacer.h"
|
|
#include "modules/rtp_rtcp/include/rtp_packet_sender.h"
|
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
|
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
|
#include "rtc_base/critical_section.h"
|
|
#include "rtc_base/experiments/field_trial_parser.h"
|
|
#include "rtc_base/thread_annotations.h"
|
|
|
|
namespace webrtc {
|
|
|
|
// This class implements a leaky-bucket packet pacing algorithm. It handles the
|
|
// logic of determining which packets to send when, but the actual timing of
|
|
// the processing is done externally (e.g. PacedSender). Furthermore, the
|
|
// forwarding of packets when they are ready to be sent is also handled
|
|
// externally, via the PacedSendingController::PacketSender interface.
|
|
//
|
|
class PacingController {
|
|
public:
|
|
// Periodic mode uses the IntervalBudget class for tracking bitrate
|
|
// budgets, and expected ProcessPackets() to be called a fixed rate,
|
|
// e.g. every 5ms as implemented by PacedSender.
|
|
// Dynamic mode allows for arbitrary time delta between calls to
|
|
// ProcessPackets.
|
|
enum class ProcessMode { kPeriodic, kDynamic };
|
|
|
|
class PacketSender {
|
|
public:
|
|
virtual ~PacketSender() = default;
|
|
virtual void SendPacket(std::unique_ptr<RtpPacketToSend> packet,
|
|
const PacedPacketInfo& cluster_info) = 0;
|
|
// Should be called after each call to SendPacket().
|
|
virtual std::vector<std::unique_ptr<RtpPacketToSend>> FetchFec() = 0;
|
|
virtual std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePadding(
|
|
DataSize size) = 0;
|
|
};
|
|
|
|
// Expected max pacer delay. If ExpectedQueueTime() is higher than
|
|
// this value, the packet producers should wait (eg drop frames rather than
|
|
// encoding them). Bitrate sent may temporarily exceed target set by
|
|
// UpdateBitrate() so that this limit will be upheld.
|
|
static const TimeDelta kMaxExpectedQueueLength;
|
|
// Pacing-rate relative to our target send rate.
|
|
// Multiplicative factor that is applied to the target bitrate to calculate
|
|
// the number of bytes that can be transmitted per interval.
|
|
// Increasing this factor will result in lower delays in cases of bitrate
|
|
// overshoots from the encoder.
|
|
static const float kDefaultPaceMultiplier;
|
|
// If no media or paused, wake up at least every |kPausedProcessIntervalMs| in
|
|
// order to send a keep-alive packet so we don't get stuck in a bad state due
|
|
// to lack of feedback.
|
|
static const TimeDelta kPausedProcessInterval;
|
|
|
|
static const TimeDelta kMinSleepTime;
|
|
|
|
PacingController(Clock* clock,
|
|
PacketSender* packet_sender,
|
|
RtcEventLog* event_log,
|
|
const WebRtcKeyValueConfig* field_trials,
|
|
ProcessMode mode);
|
|
|
|
~PacingController();
|
|
|
|
// Adds the packet to the queue and calls PacketRouter::SendPacket() when
|
|
// it's time to send.
|
|
void EnqueuePacket(std::unique_ptr<RtpPacketToSend> packet);
|
|
|
|
void CreateProbeCluster(DataRate bitrate, int cluster_id);
|
|
|
|
void Pause(); // Temporarily pause all sending.
|
|
void Resume(); // Resume sending packets.
|
|
bool IsPaused() const;
|
|
|
|
void SetCongestionWindow(DataSize congestion_window_size);
|
|
void UpdateOutstandingData(DataSize outstanding_data);
|
|
|
|
// Sets the pacing rates. Must be called once before packets can be sent.
|
|
void SetPacingRates(DataRate pacing_rate, DataRate padding_rate);
|
|
|
|
// Currently audio traffic is not accounted by pacer and passed through.
|
|
// With the introduction of audio BWE audio traffic will be accounted for
|
|
// the pacer budget calculation. The audio traffic still will be injected
|
|
// at high priority.
|
|
void SetAccountForAudioPackets(bool account_for_audio);
|
|
void SetIncludeOverhead();
|
|
|
|
void SetTransportOverhead(DataSize overhead_per_packet);
|
|
|
|
// Returns the time since the oldest queued packet was enqueued.
|
|
TimeDelta OldestPacketWaitTime() const;
|
|
|
|
// Number of packets in the pacer queue.
|
|
size_t QueueSizePackets() const;
|
|
// Totals size of packets in the pacer queue.
|
|
DataSize QueueSizeData() const;
|
|
|
|
// Current buffer level, i.e. max of media and padding debt.
|
|
DataSize CurrentBufferLevel() const;
|
|
|
|
// Returns the time when the first packet was sent;
|
|
absl::optional<Timestamp> FirstSentPacketTime() const;
|
|
|
|
// Returns the number of milliseconds it will take to send the current
|
|
// packets in the queue, given the current size and bitrate, ignoring prio.
|
|
TimeDelta ExpectedQueueTime() const;
|
|
|
|
void SetQueueTimeLimit(TimeDelta limit);
|
|
|
|
// Enable bitrate probing. Enabled by default, mostly here to simplify
|
|
// testing. Must be called before any packets are being sent to have an
|
|
// effect.
|
|
void SetProbingEnabled(bool enabled);
|
|
|
|
// Returns the next time we expect ProcessPackets() to be called.
|
|
Timestamp NextSendTime() const;
|
|
|
|
// Check queue of pending packets and send them or padding packets, if budget
|
|
// is available.
|
|
void ProcessPackets();
|
|
|
|
bool Congested() const;
|
|
|
|
bool IsProbing() const;
|
|
|
|
private:
|
|
void EnqueuePacketInternal(std::unique_ptr<RtpPacketToSend> packet,
|
|
int priority);
|
|
TimeDelta UpdateTimeAndGetElapsed(Timestamp now);
|
|
bool ShouldSendKeepalive(Timestamp now) const;
|
|
|
|
// Updates the number of bytes that can be sent for the next time interval.
|
|
void UpdateBudgetWithElapsedTime(TimeDelta delta);
|
|
void UpdateBudgetWithSentData(DataSize size);
|
|
|
|
DataSize PaddingToAdd(absl::optional<DataSize> recommended_probe_size,
|
|
DataSize data_sent) const;
|
|
|
|
std::unique_ptr<RtpPacketToSend> GetPendingPacket(
|
|
const PacedPacketInfo& pacing_info,
|
|
Timestamp target_send_time,
|
|
Timestamp now);
|
|
void OnPacketSent(RtpPacketMediaType packet_type,
|
|
DataSize packet_size,
|
|
Timestamp send_time);
|
|
void OnPaddingSent(DataSize padding_sent);
|
|
|
|
Timestamp CurrentTime() const;
|
|
|
|
const ProcessMode mode_;
|
|
Clock* const clock_;
|
|
PacketSender* const packet_sender_;
|
|
const std::unique_ptr<FieldTrialBasedConfig> fallback_field_trials_;
|
|
const WebRtcKeyValueConfig* field_trials_;
|
|
|
|
const bool drain_large_queues_;
|
|
const bool send_padding_if_silent_;
|
|
const bool pace_audio_;
|
|
const bool small_first_probe_packet_;
|
|
const bool ignore_transport_overhead_;
|
|
// In dynamic mode, indicates the target size when requesting padding,
|
|
// expressed as a duration in order to adjust for varying padding rate.
|
|
const TimeDelta padding_target_duration_;
|
|
|
|
TimeDelta min_packet_limit_;
|
|
|
|
DataSize transport_overhead_per_packet_;
|
|
|
|
// TODO(webrtc:9716): Remove this when we are certain clocks are monotonic.
|
|
// The last millisecond timestamp returned by |clock_|.
|
|
mutable Timestamp last_timestamp_;
|
|
bool paused_;
|
|
|
|
// If |use_interval_budget_| is true, |media_budget_| and |padding_budget_|
|
|
// will be used to track when packets can be sent. Otherwise the media and
|
|
// padding debt counters will be used together with the target rates.
|
|
|
|
// This is the media budget, keeping track of how many bits of media
|
|
// we can pace out during the current interval.
|
|
IntervalBudget media_budget_;
|
|
// This is the padding budget, keeping track of how many bits of padding we're
|
|
// allowed to send out during the current interval. This budget will be
|
|
// utilized when there's no media to send.
|
|
IntervalBudget padding_budget_;
|
|
|
|
DataSize media_debt_;
|
|
DataSize padding_debt_;
|
|
DataRate media_rate_;
|
|
DataRate padding_rate_;
|
|
|
|
BitrateProber prober_;
|
|
bool probing_send_failure_;
|
|
|
|
DataRate pacing_bitrate_;
|
|
|
|
Timestamp last_process_time_;
|
|
Timestamp last_send_time_;
|
|
absl::optional<Timestamp> first_sent_packet_time_;
|
|
|
|
RoundRobinPacketQueue packet_queue_;
|
|
uint64_t packet_counter_;
|
|
|
|
DataSize congestion_window_size_;
|
|
DataSize outstanding_data_;
|
|
|
|
TimeDelta queue_time_limit;
|
|
bool account_for_audio_;
|
|
bool include_overhead_;
|
|
};
|
|
} // namespace webrtc
|
|
|
|
#endif // MODULES_PACING_PACING_CONTROLLER_H_
|