Add RtpPacketHistory::SetSendTime()
This method will be used instead of GetPacketAndSetSendTime() when the new pacer code path is used, where the packet isn't stored in the history during pacing. Bug: webrtc:10633 Change-Id: Ie168125d949cef617ade3868a1858ed1dffe909c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/140892 Commit-Queue: Erik Språng <sprang@webrtc.org> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#28240}
This commit is contained in:
@ -206,6 +206,7 @@ rtc_static_library("rtp_rtcp") {
|
|||||||
"..:module_fec_api",
|
"..:module_fec_api",
|
||||||
"../..:webrtc_common",
|
"../..:webrtc_common",
|
||||||
"../../api:array_view",
|
"../../api:array_view",
|
||||||
|
"../../api:function_view",
|
||||||
"../../api:libjingle_peerconnection_api",
|
"../../api:libjingle_peerconnection_api",
|
||||||
"../../api:rtp_headers",
|
"../../api:rtp_headers",
|
||||||
"../../api:scoped_refptr",
|
"../../api:scoped_refptr",
|
||||||
|
@ -205,6 +205,71 @@ std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacketAndSetSendTime(
|
|||||||
return absl::make_unique<RtpPacketToSend>(*packet.packet_);
|
return absl::make_unique<RtpPacketToSend>(*packet.packet_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacketAndMarkAsPending(
|
||||||
|
uint16_t sequence_number) {
|
||||||
|
return GetPacketAndMarkAsPending(
|
||||||
|
sequence_number, [](const RtpPacketToSend& packet) {
|
||||||
|
return absl::make_unique<RtpPacketToSend>(packet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacketAndMarkAsPending(
|
||||||
|
uint16_t sequence_number,
|
||||||
|
rtc::FunctionView<std::unique_ptr<RtpPacketToSend>(const RtpPacketToSend&)>
|
||||||
|
encapsulate) {
|
||||||
|
rtc::CritScope cs(&lock_);
|
||||||
|
if (mode_ == StorageMode::kDisabled) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
|
StoredPacketIterator rtp_it = packet_history_.find(sequence_number);
|
||||||
|
if (rtp_it == packet_history_.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
StoredPacket& packet = rtp_it->second;
|
||||||
|
RTC_DCHECK(packet.storage_type() != StorageType::kDontRetransmit);
|
||||||
|
|
||||||
|
if (packet.pending_transmission_) {
|
||||||
|
// Packet already in pacer queue, ignore this request.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!VerifyRtt(rtp_it->second, now_ms)) {
|
||||||
|
// Packet already resent within too short a time window, ignore.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet.pending_transmission_ = true;
|
||||||
|
|
||||||
|
// Copy and/or encapsulate packet.
|
||||||
|
return encapsulate(*packet.packet_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RtpPacketHistory::MarkPacketAsSent(uint16_t sequence_number) {
|
||||||
|
rtc::CritScope cs(&lock_);
|
||||||
|
if (mode_ == StorageMode::kDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
|
StoredPacketIterator rtp_it = packet_history_.find(sequence_number);
|
||||||
|
if (rtp_it == packet_history_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StoredPacket& packet = rtp_it->second;
|
||||||
|
RTC_CHECK(packet.storage_type() != StorageType::kDontRetransmit);
|
||||||
|
RTC_DCHECK(packet.send_time_ms_);
|
||||||
|
|
||||||
|
// Update send-time, mark as no longer in pacer queue, and increment
|
||||||
|
// transmission count.
|
||||||
|
packet.send_time_ms_ = now_ms;
|
||||||
|
packet.pending_transmission_ = false;
|
||||||
|
packet.IncrementTimesRetransmitted(&padding_priority_);
|
||||||
|
}
|
||||||
|
|
||||||
absl::optional<RtpPacketHistory::PacketState> RtpPacketHistory::GetPacketState(
|
absl::optional<RtpPacketHistory::PacketState> RtpPacketHistory::GetPacketState(
|
||||||
uint16_t sequence_number) const {
|
uint16_t sequence_number) const {
|
||||||
rtc::CritScope cs(&lock_);
|
rtc::CritScope cs(&lock_);
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "api/function_view.h"
|
||||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
#include "rtc_base/constructor_magic.h"
|
#include "rtc_base/constructor_magic.h"
|
||||||
#include "rtc_base/critical_section.h"
|
#include "rtc_base/critical_section.h"
|
||||||
@ -82,6 +83,25 @@ class RtpPacketHistory {
|
|||||||
std::unique_ptr<RtpPacketToSend> GetPacketAndSetSendTime(
|
std::unique_ptr<RtpPacketToSend> GetPacketAndSetSendTime(
|
||||||
uint16_t sequence_number);
|
uint16_t sequence_number);
|
||||||
|
|
||||||
|
// Gets stored RTP packet corresponding to the input |sequence number|.
|
||||||
|
// Returns nullptr if packet is not found or was (re)sent too recently.
|
||||||
|
// If a packet copy is returned, it will be marked as pending transmission but
|
||||||
|
// does not update send time, that must be done by MarkPacketAsSent().
|
||||||
|
std::unique_ptr<RtpPacketToSend> GetPacketAndMarkAsPending(
|
||||||
|
uint16_t sequence_number);
|
||||||
|
|
||||||
|
// In addition to getting packet and marking as sent, this method takes an
|
||||||
|
// encapsulator function that takes a reference to the packet and outputs a
|
||||||
|
// copy that may be wrapped in a container, eg RTX.
|
||||||
|
std::unique_ptr<RtpPacketToSend> GetPacketAndMarkAsPending(
|
||||||
|
uint16_t sequence_number,
|
||||||
|
rtc::FunctionView<std::unique_ptr<RtpPacketToSend>(
|
||||||
|
const RtpPacketToSend&)> encapsulate);
|
||||||
|
|
||||||
|
// Updates the send time for the given packet and increments the transmission
|
||||||
|
// counter. Marks the packet as no longer being in the pacer queue.
|
||||||
|
void MarkPacketAsSent(uint16_t sequence_number);
|
||||||
|
|
||||||
// Similar to GetPacketAndSetSendTime(), but only returns a snapshot of the
|
// Similar to GetPacketAndSetSendTime(), but only returns a snapshot of the
|
||||||
// current state for packet, and never updates internal state.
|
// current state for packet, and never updates internal state.
|
||||||
absl::optional<PacketState> GetPacketState(uint16_t sequence_number) const;
|
absl::optional<PacketState> GetPacketState(uint16_t sequence_number) const;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "absl/memory/memory.h"
|
||||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
#include "system_wrappers/include/clock.h"
|
||||||
@ -678,6 +679,61 @@ TEST_F(RtpPacketHistoryTest, SetsPendingTransmissionState) {
|
|||||||
EXPECT_FALSE(packet_state->pending_transmission);
|
EXPECT_FALSE(packet_state->pending_transmission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpPacketHistoryTest, GetPacketAndSetSent) {
|
||||||
|
const int64_t kRttMs = RtpPacketHistory::kMinPacketDurationMs * 2;
|
||||||
|
hist_.SetRtt(kRttMs);
|
||||||
|
|
||||||
|
// Set size to remove old packets as soon as possible.
|
||||||
|
hist_.SetStorePacketsStatus(StorageMode::kStoreAndCull, 1);
|
||||||
|
|
||||||
|
// Add a sent packet to the history.
|
||||||
|
hist_.PutRtpPacket(CreateRtpPacket(kStartSeqNum), kAllowRetransmission,
|
||||||
|
fake_clock_.TimeInMicroseconds());
|
||||||
|
|
||||||
|
// Retransmission request, first retransmission is allowed immediately.
|
||||||
|
EXPECT_TRUE(hist_.GetPacketAndMarkAsPending(kStartSeqNum));
|
||||||
|
|
||||||
|
// Packet not yet sent, new retransmission not allowed.
|
||||||
|
fake_clock_.AdvanceTimeMilliseconds(kRttMs);
|
||||||
|
EXPECT_FALSE(hist_.GetPacketAndMarkAsPending(kStartSeqNum));
|
||||||
|
|
||||||
|
// Mark as sent, but too early for retransmission.
|
||||||
|
hist_.MarkPacketAsSent(kStartSeqNum);
|
||||||
|
EXPECT_FALSE(hist_.GetPacketAndMarkAsPending(kStartSeqNum));
|
||||||
|
|
||||||
|
// Enough time has passed, retransmission is allowed again.
|
||||||
|
fake_clock_.AdvanceTimeMilliseconds(kRttMs);
|
||||||
|
EXPECT_TRUE(hist_.GetPacketAndMarkAsPending(kStartSeqNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpPacketHistoryTest, GetPacketWithEncapsulation) {
|
||||||
|
const uint32_t kSsrc = 92384762;
|
||||||
|
const int64_t kRttMs = RtpPacketHistory::kMinPacketDurationMs * 2;
|
||||||
|
hist_.SetRtt(kRttMs);
|
||||||
|
|
||||||
|
// Set size to remove old packets as soon as possible.
|
||||||
|
hist_.SetStorePacketsStatus(StorageMode::kStoreAndCull, 1);
|
||||||
|
|
||||||
|
// Add a sent packet to the history, with a set SSRC.
|
||||||
|
std::unique_ptr<RtpPacketToSend> packet = CreateRtpPacket(kStartSeqNum);
|
||||||
|
packet->SetSsrc(kSsrc);
|
||||||
|
hist_.PutRtpPacket(std::move(packet), kAllowRetransmission,
|
||||||
|
fake_clock_.TimeInMicroseconds());
|
||||||
|
|
||||||
|
// Retransmission request, simulate an RTX-like encapsulation, were the packet
|
||||||
|
// is sent on a different SSRC.
|
||||||
|
std::unique_ptr<RtpPacketToSend> retransmit_packet =
|
||||||
|
hist_.GetPacketAndMarkAsPending(
|
||||||
|
kStartSeqNum, [](const RtpPacketToSend& packet) {
|
||||||
|
auto encapsulated_packet =
|
||||||
|
absl::make_unique<RtpPacketToSend>(packet);
|
||||||
|
encapsulated_packet->SetSsrc(packet.Ssrc() + 1);
|
||||||
|
return encapsulated_packet;
|
||||||
|
});
|
||||||
|
ASSERT_TRUE(retransmit_packet);
|
||||||
|
EXPECT_EQ(retransmit_packet->Ssrc(), kSsrc + 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(RtpPacketHistoryTest, DontRemovePendingTransmissions) {
|
TEST_F(RtpPacketHistoryTest, DontRemovePendingTransmissions) {
|
||||||
const int64_t kRttMs = RtpPacketHistory::kMinPacketDurationMs * 2;
|
const int64_t kRttMs = RtpPacketHistory::kMinPacketDurationMs * 2;
|
||||||
const int64_t kPacketTimeoutMs =
|
const int64_t kPacketTimeoutMs =
|
||||||
|
Reference in New Issue
Block a user