Index: media/cast/transport/pacing/paced_sender.cc |
diff --git a/media/cast/transport/pacing/paced_sender.cc b/media/cast/transport/pacing/paced_sender.cc |
index 10b42240759a3fd2c2580f802a7ed3b1e8b473ea..20cbde85be9ffbb906c3841b3dea9c30362be725 100644 |
--- a/media/cast/transport/pacing/paced_sender.cc |
+++ b/media/cast/transport/pacing/paced_sender.cc |
@@ -20,6 +20,7 @@ static const int64 kPacingIntervalMs = 10; |
static const size_t kPacingMaxBurstsPerFrame = 3; |
static const size_t kTargetBurstSize = 10; |
static const size_t kMaxBurstSize = 20; |
+static const size_t kMaxDedupeWindowMs = 500; |
} // namespace |
@@ -73,11 +74,21 @@ bool PacedSender::SendPackets(const SendPacketVector& packets) { |
return true; |
} |
-bool PacedSender::ResendPackets(const SendPacketVector& packets) { |
+bool PacedSender::ResendPackets(const SendPacketVector& packets, |
+ base::TimeDelta dedupe_window) { |
if (packets.empty()) { |
return true; |
} |
+ base::TimeTicks now = clock_->NowTicks(); |
for (size_t i = 0; i < packets.size(); i++) { |
+ std::map<PacketKey, base::TimeTicks>::const_iterator j = |
+ sent_time_.find(packets[i].first); |
+ |
+ if (j != sent_time_.end() && now - j->second < dedupe_window) { |
+ LogPacketEvent(packets[i].second->data, PACKET_RTX_REJECTED); |
+ continue; |
+ } |
+ |
packet_list_[packets[i].first] = |
make_pair(PacketType_Resend, packets[i].second); |
} |
@@ -108,11 +119,13 @@ void PacedSender::CancelSendingPacket(const PacketKey& packet_key) { |
packet_list_.erase(packet_key); |
} |
-PacketRef PacedSender::GetNextPacket(PacketType* packet_type) { |
+PacketRef PacedSender::GetNextPacket(PacketType* packet_type, |
+ PacketKey* packet_key) { |
std::map<PacketKey, std::pair<PacketType, PacketRef> >::iterator i; |
i = packet_list_.begin(); |
DCHECK(i != packet_list_.end()); |
*packet_type = i->second.first; |
+ *packet_key = i->first; |
PacketRef ret = i->second.second; |
packet_list_.erase(i); |
return ret; |
@@ -185,14 +198,17 @@ void PacedSender::SendStoredPackets() { |
return; |
} |
PacketType packet_type; |
- PacketRef packet = GetNextPacket(&packet_type); |
+ PacketKey packet_key; |
+ PacketRef packet = GetNextPacket(&packet_type, &packet_key); |
+ sent_time_[packet_key] = now; |
+ sent_time_buffer_[packet_key] = now; |
switch (packet_type) { |
case PacketType_Resend: |
- LogPacketEvent(packet->data, true); |
+ LogPacketEvent(packet->data, PACKET_RETRANSMITTED); |
break; |
case PacketType_Normal: |
- LogPacketEvent(packet->data, false); |
+ LogPacketEvent(packet->data, PACKET_SENT_TO_NETWORK); |
break; |
case PacketType_RTCP: |
break; |
@@ -203,10 +219,20 @@ void PacedSender::SendStoredPackets() { |
} |
current_burst_size_++; |
} |
+ // Keep ~0.5 seconds of data (1000 packets) |
+ if (sent_time_buffer_.size() >= |
+ kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs) { |
+ sent_time_.swap(sent_time_buffer_); |
+ sent_time_buffer_.clear(); |
+ } |
+ DCHECK_LE(sent_time_buffer_.size(), |
+ kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs); |
+ DCHECK_LE(sent_time_.size(), |
+ 2 * kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs); |
state_ = State_Unblocked; |
} |
-void PacedSender::LogPacketEvent(const Packet& packet, bool retransmit) { |
+void PacedSender::LogPacketEvent(const Packet& packet, CastLoggingEvent event) { |
// Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see |
// if the packet is audio or video. |
DCHECK_GE(packet.size(), 12u); |
@@ -224,8 +250,6 @@ void PacedSender::LogPacketEvent(const Packet& packet, bool retransmit) { |
return; |
} |
- CastLoggingEvent event = retransmit ? |
- PACKET_RETRANSMITTED : PACKET_SENT_TO_NETWORK; |
EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; |
logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, |
packet); |