mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 06:10:40 +01:00

Bug: webrtc:11340 Change-Id: I70a97ab3ea576e54f1b4cf02042af5e6d5d6c2de Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/300541 Auto-Submit: Erik Språng <sprang@webrtc.org> Reviewed-by: Ying Wang <yinwa@webrtc.org> Commit-Queue: Ying Wang <yinwa@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39805}
177 lines
6.5 KiB
C++
177 lines
6.5 KiB
C++
/*
|
|
* Copyright (c) 2022 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_PRIORITIZED_PACKET_QUEUE_H_
|
|
#define MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <array>
|
|
#include <deque>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "api/units/data_size.h"
|
|
#include "api/units/time_delta.h"
|
|
#include "api/units/timestamp.h"
|
|
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
|
|
|
namespace webrtc {
|
|
|
|
class PrioritizedPacketQueue {
|
|
public:
|
|
explicit PrioritizedPacketQueue(Timestamp creation_time);
|
|
PrioritizedPacketQueue(const PrioritizedPacketQueue&) = delete;
|
|
PrioritizedPacketQueue& operator=(const PrioritizedPacketQueue&) = delete;
|
|
|
|
// Add a packet to the queue. The enqueue time is used for queue time stats
|
|
// and to report the leading packet enqueue time per packet type.
|
|
void Push(Timestamp enqueue_time, std::unique_ptr<RtpPacketToSend> packet);
|
|
|
|
// Remove the next packet from the queue. Packets a prioritized first
|
|
// according to packet type, in the following order:
|
|
// - audio, retransmissions, video / fec, padding
|
|
// For each packet type, we use one FIFO-queue per SSRC and emit from
|
|
// those queues in a round-robin fashion.
|
|
std::unique_ptr<RtpPacketToSend> Pop();
|
|
|
|
// Number of packets in the queue.
|
|
int SizeInPackets() const;
|
|
|
|
// Sum of all payload bytes in the queue, where the payload is calculated
|
|
// as `packet->payload_size() + packet->padding_size()`.
|
|
DataSize SizeInPayloadBytes() const;
|
|
|
|
// Convenience method for `SizeInPackets() == 0`.
|
|
bool Empty() const;
|
|
|
|
// Total packets in the queue per media type (RtpPacketMediaType values are
|
|
// used as lookup index).
|
|
const std::array<int, kNumMediaTypes>& SizeInPacketsPerRtpPacketMediaType()
|
|
const;
|
|
|
|
// The enqueue time of the next packet this queue will return via the Pop()
|
|
// method, for the given packet type. If queue has no packets, of that type,
|
|
// returns Timestamp::MinusInfinity().
|
|
Timestamp LeadingPacketEnqueueTime(RtpPacketMediaType type) const;
|
|
|
|
// Enqueue time of the oldest packet in the queue,
|
|
// Timestamp::MinusInfinity() if queue is empty.
|
|
Timestamp OldestEnqueueTime() const;
|
|
|
|
// Average queue time for the packets currently in the queue.
|
|
// The queuing time is calculated from Push() to the last UpdateQueueTime()
|
|
// call - with any time spent in a paused state subtracted.
|
|
// Returns TimeDelta::Zero() for an empty queue.
|
|
TimeDelta AverageQueueTime() const;
|
|
|
|
// Called during packet processing or when pause stats changes. Since the
|
|
// AverageQueueTime() method does not look at the wall time, this method
|
|
// needs to be called before querying queue time.
|
|
void UpdateAverageQueueTime(Timestamp now);
|
|
|
|
// Set the pause state, while `paused` is true queuing time is not counted.
|
|
void SetPauseState(bool paused, Timestamp now);
|
|
|
|
// Remove any packets matching the given SSRC.
|
|
void RemovePacketsForSsrc(uint32_t ssrc);
|
|
|
|
// Checks if the queue for the given SSRC has original (retransmissions not
|
|
// counted) video packets containing keyframe data.
|
|
bool HasKeyframePackets(uint32_t ssrc) const;
|
|
|
|
private:
|
|
static constexpr int kNumPriorityLevels = 4;
|
|
|
|
class QueuedPacket {
|
|
public:
|
|
DataSize PacketSize() const;
|
|
|
|
std::unique_ptr<RtpPacketToSend> packet;
|
|
Timestamp enqueue_time;
|
|
std::list<Timestamp>::iterator enqueue_time_iterator;
|
|
};
|
|
|
|
// Class containing packets for an RTP stream.
|
|
// For each priority level, packets are simply stored in a fifo queue.
|
|
class StreamQueue {
|
|
public:
|
|
explicit StreamQueue(Timestamp creation_time);
|
|
StreamQueue(StreamQueue&&) = default;
|
|
StreamQueue& operator=(StreamQueue&&) = default;
|
|
|
|
StreamQueue(const StreamQueue&) = delete;
|
|
StreamQueue& operator=(const StreamQueue&) = delete;
|
|
|
|
// Enqueue packet at the given priority level. Returns true if the packet
|
|
// count for that priority level went from zero to non-zero.
|
|
bool EnqueuePacket(QueuedPacket packet, int priority_level);
|
|
|
|
QueuedPacket DequeuePacket(int priority_level);
|
|
|
|
bool HasPacketsAtPrio(int priority_level) const;
|
|
bool IsEmpty() const;
|
|
Timestamp LeadingPacketEnqueueTime(int priority_level) const;
|
|
Timestamp LastEnqueueTime() const;
|
|
bool has_keyframe_packets() const { return num_keyframe_packets_ > 0; }
|
|
|
|
std::array<std::deque<QueuedPacket>, kNumPriorityLevels> DequeueAll();
|
|
|
|
private:
|
|
std::deque<QueuedPacket> packets_[kNumPriorityLevels];
|
|
Timestamp last_enqueue_time_;
|
|
int num_keyframe_packets_;
|
|
};
|
|
|
|
// Remove the packet from the internal state, e.g. queue time / size etc.
|
|
void DequeuePacketInternal(QueuedPacket& packet);
|
|
|
|
// Check if the queue pointed to by `top_active_prio_level_` is empty and
|
|
// if so move it to the lowest non-empty index.
|
|
void MaybeUpdateTopPrioLevel();
|
|
|
|
// Cumulative sum, over all packets, of time spent in the queue.
|
|
TimeDelta queue_time_sum_;
|
|
// Cumulative sum of time the queue has spent in a paused state.
|
|
TimeDelta pause_time_sum_;
|
|
// Total number of packets stored in this queue.
|
|
int size_packets_;
|
|
// Total number of packets stored in this queue per RtpPacketMediaType.
|
|
std::array<int, kNumMediaTypes> size_packets_per_media_type_;
|
|
// Sum of payload sizes for all packts stored in this queue.
|
|
DataSize size_payload_;
|
|
// The last time queue/pause time sums were updated.
|
|
Timestamp last_update_time_;
|
|
bool paused_;
|
|
|
|
// Last time `streams_` was culled for inactive streams.
|
|
Timestamp last_culling_time_;
|
|
|
|
// Map from SSRC to packet queues for the associated RTP stream.
|
|
std::unordered_map<uint32_t, std::unique_ptr<StreamQueue>> streams_;
|
|
|
|
// For each priority level, a queue of StreamQueues which have at least one
|
|
// packet pending for that prio level.
|
|
std::deque<StreamQueue*> streams_by_prio_[kNumPriorityLevels];
|
|
|
|
// The first index into `stream_by_prio_` that is non-empty.
|
|
int top_active_prio_level_;
|
|
|
|
// Ordered list of enqueue times. Additions are always increasing and added to
|
|
// the end. QueuedPacket instances have a iterators into this list for fast
|
|
// removal.
|
|
std::list<Timestamp> enqueue_times_;
|
|
};
|
|
|
|
} // namespace webrtc
|
|
|
|
#endif // MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_
|