Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: media/cast/transport/pacing/paced_sender.cc

Issue 343523005: Cast: Avoid retransmit if we sent the same packet recently (less than RTT) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: bugfix Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/cast/transport/pacing/paced_sender.h" 5 #include "media/cast/transport/pacing/paced_sender.h"
6 6
7 #include "base/big_endian.h" 7 #include "base/big_endian.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 10
11 namespace media { 11 namespace media {
12 namespace cast { 12 namespace cast {
13 namespace transport { 13 namespace transport {
14 14
15 namespace { 15 namespace {
16 16
17 static const int64 kPacingIntervalMs = 10; 17 static const int64 kPacingIntervalMs = 10;
18 // Each frame will be split into no more than kPacingMaxBurstsPerFrame 18 // Each frame will be split into no more than kPacingMaxBurstsPerFrame
19 // bursts of packets. 19 // bursts of packets.
20 static const size_t kPacingMaxBurstsPerFrame = 3; 20 static const size_t kPacingMaxBurstsPerFrame = 3;
21 static const size_t kTargetBurstSize = 10; 21 static const size_t kTargetBurstSize = 10;
22 static const size_t kMaxBurstSize = 20; 22 static const size_t kMaxBurstSize = 20;
23 static const size_t kMaxDedupeWindowMs = 500;
23 24
24 } // namespace 25 } // namespace
25 26
26 // static 27 // static
27 PacketKey PacedPacketSender::MakePacketKey(const base::TimeTicks& ticks, 28 PacketKey PacedPacketSender::MakePacketKey(const base::TimeTicks& ticks,
28 uint32 ssrc, 29 uint32 ssrc,
29 uint16 packet_id) { 30 uint16 packet_id) {
30 return std::make_pair(ticks, std::make_pair(ssrc, packet_id)); 31 return std::make_pair(ticks, std::make_pair(ssrc, packet_id));
31 } 32 }
32 33
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 for (size_t i = 0; i < packets.size(); i++) { 67 for (size_t i = 0; i < packets.size(); i++) {
67 packet_list_[packets[i].first] = 68 packet_list_[packets[i].first] =
68 make_pair(PacketType_Normal, packets[i].second); 69 make_pair(PacketType_Normal, packets[i].second);
69 } 70 }
70 if (state_ == State_Unblocked) { 71 if (state_ == State_Unblocked) {
71 SendStoredPackets(); 72 SendStoredPackets();
72 } 73 }
73 return true; 74 return true;
74 } 75 }
75 76
76 bool PacedSender::ResendPackets(const SendPacketVector& packets) { 77 bool PacedSender::ResendPackets(const SendPacketVector& packets,
78 base::TimeDelta dedupe_window) {
77 if (packets.empty()) { 79 if (packets.empty()) {
78 return true; 80 return true;
79 } 81 }
82 base::TimeTicks now = clock_->NowTicks();
80 for (size_t i = 0; i < packets.size(); i++) { 83 for (size_t i = 0; i < packets.size(); i++) {
84 std::map<PacketKey, base::TimeTicks>::const_iterator j =
85 sent_time_.find(packets[i].first);
86
87 if (j != sent_time_.end() && now - j->second < dedupe_window) {
88 LogPacketEvent(packets[i].second->data, PACKET_RTX_REJECTED);
89 continue;
90 }
91
81 packet_list_[packets[i].first] = 92 packet_list_[packets[i].first] =
82 make_pair(PacketType_Resend, packets[i].second); 93 make_pair(PacketType_Resend, packets[i].second);
83 } 94 }
84 if (state_ == State_Unblocked) { 95 if (state_ == State_Unblocked) {
85 SendStoredPackets(); 96 SendStoredPackets();
86 } 97 }
87 return true; 98 return true;
88 } 99 }
89 100
90 bool PacedSender::SendRtcpPacket(uint32 ssrc, PacketRef packet) { 101 bool PacedSender::SendRtcpPacket(uint32 ssrc, PacketRef packet) {
(...skipping 10 matching lines...) Expand all
101 } 112 }
102 113
103 } 114 }
104 return true; 115 return true;
105 } 116 }
106 117
107 void PacedSender::CancelSendingPacket(const PacketKey& packet_key) { 118 void PacedSender::CancelSendingPacket(const PacketKey& packet_key) {
108 packet_list_.erase(packet_key); 119 packet_list_.erase(packet_key);
109 } 120 }
110 121
111 PacketRef PacedSender::GetNextPacket(PacketType* packet_type) { 122 PacketRef PacedSender::GetNextPacket(PacketType* packet_type,
123 PacketKey* packet_key) {
112 std::map<PacketKey, std::pair<PacketType, PacketRef> >::iterator i; 124 std::map<PacketKey, std::pair<PacketType, PacketRef> >::iterator i;
113 i = packet_list_.begin(); 125 i = packet_list_.begin();
114 DCHECK(i != packet_list_.end()); 126 DCHECK(i != packet_list_.end());
115 *packet_type = i->second.first; 127 *packet_type = i->second.first;
128 *packet_key = i->first;
116 PacketRef ret = i->second.second; 129 PacketRef ret = i->second.second;
117 packet_list_.erase(i); 130 packet_list_.erase(i);
118 return ret; 131 return ret;
119 } 132 }
120 133
121 bool PacedSender::empty() const { 134 bool PacedSender::empty() const {
122 return packet_list_.empty(); 135 return packet_list_.empty();
123 } 136 }
124 137
125 size_t PacedSender::size() const { 138 size_t PacedSender::size() const {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 weak_factory_.GetWeakPtr()); 191 weak_factory_.GetWeakPtr());
179 while (!empty()) { 192 while (!empty()) {
180 if (current_burst_size_ >= max_burst_size_) { 193 if (current_burst_size_ >= max_burst_size_) {
181 transport_task_runner_->PostDelayedTask(FROM_HERE, 194 transport_task_runner_->PostDelayedTask(FROM_HERE,
182 cb, 195 cb,
183 burst_end_ - now); 196 burst_end_ - now);
184 state_ = State_BurstFull; 197 state_ = State_BurstFull;
185 return; 198 return;
186 } 199 }
187 PacketType packet_type; 200 PacketType packet_type;
188 PacketRef packet = GetNextPacket(&packet_type); 201 PacketKey packet_key;
202 PacketRef packet = GetNextPacket(&packet_type, &packet_key);
203 sent_time_[packet_key] = now;
204 sent_time_buffer_[packet_key] = now;
189 205
190 switch (packet_type) { 206 switch (packet_type) {
191 case PacketType_Resend: 207 case PacketType_Resend:
192 LogPacketEvent(packet->data, true); 208 LogPacketEvent(packet->data, PACKET_RETRANSMITTED);
193 break; 209 break;
194 case PacketType_Normal: 210 case PacketType_Normal:
195 LogPacketEvent(packet->data, false); 211 LogPacketEvent(packet->data, PACKET_SENT_TO_NETWORK);
196 break; 212 break;
197 case PacketType_RTCP: 213 case PacketType_RTCP:
198 break; 214 break;
199 } 215 }
200 if (!transport_->SendPacket(packet, cb)) { 216 if (!transport_->SendPacket(packet, cb)) {
201 state_ = State_TransportBlocked; 217 state_ = State_TransportBlocked;
202 return; 218 return;
203 } 219 }
204 current_burst_size_++; 220 current_burst_size_++;
205 } 221 }
222 // Keep ~0.5 seconds of data (1000 packets)
223 if (sent_time_buffer_.size() >=
224 kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs) {
225 sent_time_.swap(sent_time_buffer_);
226 sent_time_buffer_.clear();
227 }
228 DCHECK_LE(sent_time_buffer_.size(),
229 kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs);
230 DCHECK_LE(sent_time_.size(),
231 2 * kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs);
206 state_ = State_Unblocked; 232 state_ = State_Unblocked;
207 } 233 }
208 234
209 void PacedSender::LogPacketEvent(const Packet& packet, bool retransmit) { 235 void PacedSender::LogPacketEvent(const Packet& packet, CastLoggingEvent event) {
210 // Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see 236 // Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see
211 // if the packet is audio or video. 237 // if the packet is audio or video.
212 DCHECK_GE(packet.size(), 12u); 238 DCHECK_GE(packet.size(), 12u);
213 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[8]), 4); 239 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[8]), 4);
214 uint32 ssrc; 240 uint32 ssrc;
215 bool success = reader.ReadU32(&ssrc); 241 bool success = reader.ReadU32(&ssrc);
216 DCHECK(success); 242 DCHECK(success);
217 bool is_audio; 243 bool is_audio;
218 if (ssrc == audio_ssrc_) { 244 if (ssrc == audio_ssrc_) {
219 is_audio = true; 245 is_audio = true;
220 } else if (ssrc == video_ssrc_) { 246 } else if (ssrc == video_ssrc_) {
221 is_audio = false; 247 is_audio = false;
222 } else { 248 } else {
223 DVLOG(3) << "Got unknown ssrc " << ssrc << " when logging packet event"; 249 DVLOG(3) << "Got unknown ssrc " << ssrc << " when logging packet event";
224 return; 250 return;
225 } 251 }
226 252
227 CastLoggingEvent event = retransmit ?
228 PACKET_RETRANSMITTED : PACKET_SENT_TO_NETWORK;
229 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; 253 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT;
230 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, 254 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type,
231 packet); 255 packet);
232 } 256 }
233 257
234 } // namespace transport 258 } // namespace transport
235 } // namespace cast 259 } // namespace cast
236 } // namespace media 260 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/transport/pacing/paced_sender.h ('k') | media/cast/transport/pacing/paced_sender_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698