OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/net/pacing/paced_sender.h" | 5 #include "media/cast/net/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 #include "media/cast/logging/logging_impl.h" | 10 #include "media/cast/logging/logging_impl.h" |
11 | 11 |
12 namespace media { | 12 namespace media { |
13 namespace cast { | 13 namespace cast { |
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; | |
22 static const size_t kMaxBurstSize = 20; | |
23 static const size_t kMaxDedupeWindowMs = 500; | 21 static const size_t kMaxDedupeWindowMs = 500; |
24 | 22 |
25 // Number of packets that we keep the information of sent time and sent bytes. | |
26 // This number allows 0.5 seconds of history if sending at maximum rate. | |
27 static const size_t kPacketHistorySize = | |
28 kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs; | |
29 | |
30 } // namespace | 23 } // namespace |
31 | 24 |
32 DedupInfo::DedupInfo() : last_byte_acked_for_audio(0) {} | 25 DedupInfo::DedupInfo() : last_byte_acked_for_audio(0) {} |
33 | 26 |
34 // static | 27 // static |
35 PacketKey PacedPacketSender::MakePacketKey(const base::TimeTicks& ticks, | 28 PacketKey PacedPacketSender::MakePacketKey(const base::TimeTicks& ticks, |
36 uint32 ssrc, | 29 uint32 ssrc, |
37 uint16 packet_id) { | 30 uint16 packet_id) { |
38 return std::make_pair(ticks, std::make_pair(ssrc, packet_id)); | 31 return std::make_pair(ticks, std::make_pair(ssrc, packet_id)); |
39 } | 32 } |
40 | 33 |
41 PacedSender::PacketSendRecord::PacketSendRecord() | 34 PacedSender::PacketSendRecord::PacketSendRecord() |
42 : last_byte_sent(0), last_byte_sent_for_audio(0) {} | 35 : last_byte_sent(0), last_byte_sent_for_audio(0) {} |
43 | 36 |
44 PacedSender::PacedSender( | 37 PacedSender::PacedSender( |
| 38 size_t target_burst_size, |
| 39 size_t max_burst_size, |
45 base::TickClock* clock, | 40 base::TickClock* clock, |
46 LoggingImpl* logging, | 41 LoggingImpl* logging, |
47 PacketSender* transport, | 42 PacketSender* transport, |
48 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) | 43 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) |
49 : clock_(clock), | 44 : clock_(clock), |
50 logging_(logging), | 45 logging_(logging), |
51 transport_(transport), | 46 transport_(transport), |
52 transport_task_runner_(transport_task_runner), | 47 transport_task_runner_(transport_task_runner), |
53 audio_ssrc_(0), | 48 audio_ssrc_(0), |
54 video_ssrc_(0), | 49 video_ssrc_(0), |
55 max_burst_size_(kTargetBurstSize), | 50 target_burst_size_(target_burst_size), |
56 next_max_burst_size_(kTargetBurstSize), | 51 max_burst_size_(max_burst_size), |
57 next_next_max_burst_size_(kTargetBurstSize), | 52 current_max_burst_size_(target_burst_size_), |
| 53 next_max_burst_size_(target_burst_size_), |
| 54 next_next_max_burst_size_(target_burst_size_), |
58 current_burst_size_(0), | 55 current_burst_size_(0), |
59 state_(State_Unblocked), | 56 state_(State_Unblocked), |
60 weak_factory_(this) { | 57 weak_factory_(this) { |
61 } | 58 } |
62 | 59 |
63 PacedSender::~PacedSender() {} | 60 PacedSender::~PacedSender() {} |
64 | 61 |
65 void PacedSender::RegisterAudioSsrc(uint32 audio_ssrc) { | 62 void PacedSender::RegisterAudioSsrc(uint32 audio_ssrc) { |
66 audio_ssrc_ = audio_ssrc; | 63 audio_ssrc_ = audio_ssrc; |
67 } | 64 } |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 // three bursts, while trying to keep the burst size below 10 if possible. | 235 // three bursts, while trying to keep the burst size below 10 if possible. |
239 // We have some evidence that sending more than 12 packets in a row doesn't | 236 // We have some evidence that sending more than 12 packets in a row doesn't |
240 // work very well, but we don't actually know why yet. Sending out packets | 237 // work very well, but we don't actually know why yet. Sending out packets |
241 // sooner is better than sending out packets later as that gives us more | 238 // sooner is better than sending out packets later as that gives us more |
242 // time to re-send them if needed. So if we have less than 30 packets, just | 239 // time to re-send them if needed. So if we have less than 30 packets, just |
243 // send 10 at a time. If we have less than 60 packets, send n / 3 at a time. | 240 // send 10 at a time. If we have less than 60 packets, send n / 3 at a time. |
244 // if we have more than 60, we send 20 at a time. 20 packets is ~24Mbit/s | 241 // if we have more than 60, we send 20 at a time. 20 packets is ~24Mbit/s |
245 // which is more bandwidth than the cast library should need, and sending | 242 // which is more bandwidth than the cast library should need, and sending |
246 // out more data per second is unlikely to be helpful. | 243 // out more data per second is unlikely to be helpful. |
247 size_t max_burst_size = std::min( | 244 size_t max_burst_size = std::min( |
248 kMaxBurstSize, | 245 max_burst_size_, |
249 std::max(kTargetBurstSize, size() / kPacingMaxBurstsPerFrame)); | 246 std::max(target_burst_size_, size() / kPacingMaxBurstsPerFrame)); |
250 | 247 |
251 // If the queue is long, issue a warning. Try to limit the number of | 248 // If the queue is long, issue a warning. Try to limit the number of |
252 // warnings issued by only issuing the warning when the burst size | 249 // warnings issued by only issuing the warning when the burst size |
253 // grows. Otherwise we might get 100 warnings per second. | 250 // grows. Otherwise we might get 100 warnings per second. |
254 if (max_burst_size > next_next_max_burst_size_ && size() > 100) { | 251 if (max_burst_size > next_next_max_burst_size_ && size() > 100) { |
255 LOG(WARNING) << "Packet queue is very long:" << size(); | 252 LOG(WARNING) << "Packet queue is very long:" << size(); |
256 } | 253 } |
257 | 254 |
258 max_burst_size_ = std::max(next_max_burst_size_, max_burst_size); | 255 current_max_burst_size_ = std::max(next_max_burst_size_, max_burst_size); |
259 next_max_burst_size_ = std::max(next_next_max_burst_size_, max_burst_size); | 256 next_max_burst_size_ = std::max(next_next_max_burst_size_, max_burst_size); |
260 next_next_max_burst_size_ = max_burst_size; | 257 next_next_max_burst_size_ = max_burst_size; |
261 } | 258 } |
262 | 259 |
263 base::Closure cb = base::Bind(&PacedSender::SendStoredPackets, | 260 base::Closure cb = base::Bind(&PacedSender::SendStoredPackets, |
264 weak_factory_.GetWeakPtr()); | 261 weak_factory_.GetWeakPtr()); |
265 while (!empty()) { | 262 while (!empty()) { |
266 if (current_burst_size_ >= max_burst_size_) { | 263 if (current_burst_size_ >= current_max_burst_size_) { |
267 transport_task_runner_->PostDelayedTask(FROM_HERE, | 264 transport_task_runner_->PostDelayedTask(FROM_HERE, |
268 cb, | 265 cb, |
269 burst_end_ - now); | 266 burst_end_ - now); |
270 state_ = State_BurstFull; | 267 state_ = State_BurstFull; |
271 return; | 268 return; |
272 } | 269 } |
273 PacketType packet_type; | 270 PacketType packet_type; |
274 PacketKey packet_key; | 271 PacketKey packet_key; |
275 PacketRef packet = PopNextPacket(&packet_type, &packet_key); | 272 PacketRef packet = PopNextPacket(&packet_type, &packet_key); |
276 PacketSendRecord send_record; | 273 PacketSendRecord send_record; |
(...skipping 20 matching lines...) Expand all Loading... |
297 last_byte_sent_[packet_key.second.first] = send_record.last_byte_sent; | 294 last_byte_sent_[packet_key.second.first] = send_record.last_byte_sent; |
298 | 295 |
299 if (socket_blocked) { | 296 if (socket_blocked) { |
300 state_ = State_TransportBlocked; | 297 state_ = State_TransportBlocked; |
301 return; | 298 return; |
302 } | 299 } |
303 current_burst_size_++; | 300 current_burst_size_++; |
304 } | 301 } |
305 | 302 |
306 // Keep ~0.5 seconds of data (1000 packets). | 303 // Keep ~0.5 seconds of data (1000 packets). |
307 if (send_history_buffer_.size() >= kPacketHistorySize) { | 304 if (send_history_buffer_.size() >= |
| 305 max_burst_size_ * kMaxDedupeWindowMs / kPacingIntervalMs) { |
308 send_history_.swap(send_history_buffer_); | 306 send_history_.swap(send_history_buffer_); |
309 send_history_buffer_.clear(); | 307 send_history_buffer_.clear(); |
310 } | 308 } |
311 DCHECK_LE(send_history_buffer_.size(), kPacketHistorySize); | 309 DCHECK_LE(send_history_buffer_.size(), |
| 310 max_burst_size_ * kMaxDedupeWindowMs / kPacingIntervalMs); |
312 state_ = State_Unblocked; | 311 state_ = State_Unblocked; |
313 } | 312 } |
314 | 313 |
315 void PacedSender::LogPacketEvent(const Packet& packet, CastLoggingEvent event) { | 314 void PacedSender::LogPacketEvent(const Packet& packet, CastLoggingEvent event) { |
316 // Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see | 315 // Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see |
317 // if the packet is audio or video. | 316 // if the packet is audio or video. |
318 DCHECK_GE(packet.size(), 12u); | 317 DCHECK_GE(packet.size(), 12u); |
319 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[8]), 4); | 318 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[8]), 4); |
320 uint32 ssrc; | 319 uint32 ssrc; |
321 bool success = reader.ReadU32(&ssrc); | 320 bool success = reader.ReadU32(&ssrc); |
322 DCHECK(success); | 321 DCHECK(success); |
323 bool is_audio; | 322 bool is_audio; |
324 if (ssrc == audio_ssrc_) { | 323 if (ssrc == audio_ssrc_) { |
325 is_audio = true; | 324 is_audio = true; |
326 } else if (ssrc == video_ssrc_) { | 325 } else if (ssrc == video_ssrc_) { |
327 is_audio = false; | 326 is_audio = false; |
328 } else { | 327 } else { |
329 DVLOG(3) << "Got unknown ssrc " << ssrc << " when logging packet event"; | 328 DVLOG(3) << "Got unknown ssrc " << ssrc << " when logging packet event"; |
330 return; | 329 return; |
331 } | 330 } |
332 | 331 |
333 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; | 332 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; |
334 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, | 333 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, |
335 packet); | 334 packet); |
336 } | 335 } |
337 | 336 |
338 } // namespace cast | 337 } // namespace cast |
339 } // namespace media | 338 } // namespace media |
OLD | NEW |