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/debug/dump_without_crashing.h" | 9 #include "base/debug/dump_without_crashing.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 uint16_t packet_id) | 39 uint16_t packet_id) |
40 : capture_time(capture_time), | 40 : capture_time(capture_time), |
41 ssrc(ssrc), | 41 ssrc(ssrc), |
42 frame_id(frame_id), | 42 frame_id(frame_id), |
43 packet_id(packet_id) {} | 43 packet_id(packet_id) {} |
44 | 44 |
45 PacketKey::PacketKey(const PacketKey& other) = default; | 45 PacketKey::PacketKey(const PacketKey& other) = default; |
46 | 46 |
47 PacketKey::~PacketKey() {} | 47 PacketKey::~PacketKey() {} |
48 | 48 |
49 PacedSender::PacketSendRecord::PacketSendRecord() | 49 struct PacedSender::PacketSendRecord { |
50 : last_byte_sent(0), last_byte_sent_for_audio(0), cancel_count(0) {} | 50 PacketSendRecord() |
| 51 : last_byte_sent(0), last_byte_sent_for_audio(0), cancel_count(0) {} |
| 52 |
| 53 base::TimeTicks time; // Time when the packet was sent. |
| 54 int64_t last_byte_sent; // Number of bytes sent to network just after this |
| 55 // packet was sent. |
| 56 int64_t last_byte_sent_for_audio; // Number of bytes sent to network from |
| 57 // audio stream just before this packet. |
| 58 int cancel_count; // Number of times the packet was canceled (debugging). |
| 59 }; |
| 60 |
| 61 struct PacedSender::RtpSession { |
| 62 explicit RtpSession(bool is_audio_stream) |
| 63 : last_byte_sent(0), is_audio(is_audio_stream) {} |
| 64 RtpSession() {} |
| 65 |
| 66 // Tracks recently-logged RTP timestamps so that it can expand the truncated |
| 67 // values found in packets. |
| 68 RtpTimeTicks last_logged_rtp_timestamp_; |
| 69 int64_t last_byte_sent; |
| 70 bool is_audio; |
| 71 }; |
51 | 72 |
52 PacedSender::PacedSender( | 73 PacedSender::PacedSender( |
53 size_t target_burst_size, | 74 size_t target_burst_size, |
54 size_t max_burst_size, | 75 size_t max_burst_size, |
55 base::TickClock* clock, | 76 base::TickClock* clock, |
56 std::vector<PacketEvent>* recent_packet_events, | 77 std::vector<PacketEvent>* recent_packet_events, |
57 PacketTransport* transport, | 78 PacketTransport* transport, |
58 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) | 79 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) |
59 : clock_(clock), | 80 : clock_(clock), |
60 recent_packet_events_(recent_packet_events), | 81 recent_packet_events_(recent_packet_events), |
61 transport_(transport), | 82 transport_(transport), |
62 transport_task_runner_(transport_task_runner), | 83 transport_task_runner_(transport_task_runner), |
63 audio_ssrc_(0), | 84 last_byte_sent_for_audio_(0), |
64 video_ssrc_(0), | |
65 target_burst_size_(target_burst_size), | 85 target_burst_size_(target_burst_size), |
66 max_burst_size_(max_burst_size), | 86 max_burst_size_(max_burst_size), |
67 current_max_burst_size_(target_burst_size_), | 87 current_max_burst_size_(target_burst_size_), |
68 next_max_burst_size_(target_burst_size_), | 88 next_max_burst_size_(target_burst_size_), |
69 next_next_max_burst_size_(target_burst_size_), | 89 next_next_max_burst_size_(target_burst_size_), |
70 current_burst_size_(0), | 90 current_burst_size_(0), |
71 state_(State_Unblocked), | 91 state_(State_Unblocked), |
72 has_reached_upper_bound_once_(false), | 92 has_reached_upper_bound_once_(false), |
73 weak_factory_(this) {} | 93 weak_factory_(this) {} |
74 | 94 |
75 PacedSender::~PacedSender() {} | 95 PacedSender::~PacedSender() {} |
76 | 96 |
77 void PacedSender::RegisterAudioSsrc(uint32_t audio_ssrc) { | 97 void PacedSender::RegisterSsrc(uint32_t ssrc, bool is_audio) { |
78 audio_ssrc_ = audio_ssrc; | 98 if (sessions_.find(ssrc) != sessions_.end()) |
79 } | 99 DVLOG(1) << "Re-register ssrc: " << ssrc; |
80 | 100 |
81 void PacedSender::RegisterVideoSsrc(uint32_t video_ssrc) { | 101 sessions_[ssrc] = RtpSession(is_audio); |
82 video_ssrc_ = video_ssrc; | |
83 } | 102 } |
84 | 103 |
85 void PacedSender::RegisterPrioritySsrc(uint32_t ssrc) { | 104 void PacedSender::RegisterPrioritySsrc(uint32_t ssrc) { |
86 priority_ssrcs_.push_back(ssrc); | 105 priority_ssrcs_.push_back(ssrc); |
87 } | 106 } |
88 | 107 |
89 int64_t PacedSender::GetLastByteSentForPacket(const PacketKey& packet_key) { | 108 int64_t PacedSender::GetLastByteSentForPacket(const PacketKey& packet_key) { |
90 PacketSendHistory::const_iterator it = send_history_.find(packet_key); | 109 PacketSendHistory::const_iterator it = send_history_.find(packet_key); |
91 if (it == send_history_.end()) | 110 if (it == send_history_.end()) |
92 return 0; | 111 return 0; |
93 return it->second.last_byte_sent; | 112 return it->second.last_byte_sent; |
94 } | 113 } |
95 | 114 |
96 int64_t PacedSender::GetLastByteSentForSsrc(uint32_t ssrc) { | 115 int64_t PacedSender::GetLastByteSentForSsrc(uint32_t ssrc) { |
97 std::map<uint32_t, int64_t>::const_iterator it = last_byte_sent_.find(ssrc); | 116 auto it = sessions_.find(ssrc); |
98 if (it == last_byte_sent_.end()) | 117 // Return 0 for unknown session. |
| 118 if (it == sessions_.end()) |
99 return 0; | 119 return 0; |
100 return it->second; | 120 return it->second.last_byte_sent; |
101 } | 121 } |
102 | 122 |
103 bool PacedSender::SendPackets(const SendPacketVector& packets) { | 123 bool PacedSender::SendPackets(const SendPacketVector& packets) { |
104 if (packets.empty()) { | 124 if (packets.empty()) { |
105 return true; | 125 return true; |
106 } | 126 } |
107 const bool high_priority = IsHighPriority(packets.begin()->first); | 127 const bool high_priority = IsHighPriority(packets.begin()->first); |
108 for (size_t i = 0; i < packets.size(); i++) { | 128 for (size_t i = 0; i < packets.size(); i++) { |
109 if (VLOG_IS_ON(2)) { | 129 if (VLOG_IS_ON(2)) { |
110 PacketSendHistory::const_iterator history_it = | 130 PacketSendHistory::const_iterator history_it = |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 if (it == send_history_.end()) | 163 if (it == send_history_.end()) |
144 return true; | 164 return true; |
145 | 165 |
146 // Suppose there is request to retransmit X and there is an audio | 166 // Suppose there is request to retransmit X and there is an audio |
147 // packet Y sent just before X. Reject retransmission of X if ACK for | 167 // packet Y sent just before X. Reject retransmission of X if ACK for |
148 // Y has not been received. | 168 // Y has not been received. |
149 // Only do this for video packets. | 169 // Only do this for video packets. |
150 // | 170 // |
151 // TODO(miu): This sounds wrong. Audio packets are always transmitted first | 171 // TODO(miu): This sounds wrong. Audio packets are always transmitted first |
152 // (because they are put in |priority_packet_list_|, see PopNextPacket()). | 172 // (because they are put in |priority_packet_list_|, see PopNextPacket()). |
153 if (packet_key.ssrc == video_ssrc_) { | 173 auto session_it = sessions_.find(packet_key.ssrc); |
| 174 // The session should always have been registered in |sessions_|. |
| 175 DCHECK(session_it != sessions_.end()); |
| 176 if (!session_it->second.is_audio) { |
154 if (dedup_info.last_byte_acked_for_audio && | 177 if (dedup_info.last_byte_acked_for_audio && |
155 it->second.last_byte_sent_for_audio && | 178 it->second.last_byte_sent_for_audio && |
156 dedup_info.last_byte_acked_for_audio < | 179 dedup_info.last_byte_acked_for_audio < |
157 it->second.last_byte_sent_for_audio) { | 180 it->second.last_byte_sent_for_audio) { |
158 return false; | 181 return false; |
159 } | 182 } |
160 } | 183 } |
161 // Retransmission interval has to be greater than |resend_interval|. | 184 // Retransmission interval has to be greater than |resend_interval|. |
162 if (now - it->second.time < dedup_info.resend_interval) | 185 if (now - it->second.time < dedup_info.resend_interval) |
163 return false; | 186 return false; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 LogPacketEvent(packet->data, PACKET_SENT_TO_NETWORK); | 405 LogPacketEvent(packet->data, PACKET_SENT_TO_NETWORK); |
383 break; | 406 break; |
384 case PacketType_RTCP: | 407 case PacketType_RTCP: |
385 break; | 408 break; |
386 } | 409 } |
387 | 410 |
388 const bool socket_blocked = !transport_->SendPacket(packet, cb); | 411 const bool socket_blocked = !transport_->SendPacket(packet, cb); |
389 | 412 |
390 // Save the send record. | 413 // Save the send record. |
391 send_record->last_byte_sent = transport_->GetBytesSent(); | 414 send_record->last_byte_sent = transport_->GetBytesSent(); |
392 send_record->last_byte_sent_for_audio = GetLastByteSentForSsrc(audio_ssrc_); | 415 send_record->last_byte_sent_for_audio = last_byte_sent_for_audio_; |
393 send_history_buffer_[packet_key] = *send_record; | 416 send_history_buffer_[packet_key] = *send_record; |
394 last_byte_sent_[packet_key.ssrc] = send_record->last_byte_sent; | 417 |
| 418 auto it = sessions_.find(packet_key.ssrc); |
| 419 // The session should always have been registered in |sessions_|. |
| 420 DCHECK(it != sessions_.end()); |
| 421 it->second.last_byte_sent = send_record->last_byte_sent; |
| 422 if (it->second.is_audio) |
| 423 last_byte_sent_for_audio_ = send_record->last_byte_sent; |
395 | 424 |
396 if (socket_blocked) { | 425 if (socket_blocked) { |
397 state_ = State_TransportBlocked; | 426 state_ = State_TransportBlocked; |
398 return; | 427 return; |
399 } | 428 } |
400 current_burst_size_++; | 429 current_burst_size_++; |
401 } | 430 } |
402 | 431 |
403 // Keep ~0.5 seconds of data (1000 packets). | 432 // Keep ~0.5 seconds of data (1000 packets). |
404 // | 433 // |
(...skipping 21 matching lines...) Expand all Loading... |
426 // TODO(miu): This parsing logic belongs in RtpParser. | 455 // TODO(miu): This parsing logic belongs in RtpParser. |
427 event.timestamp = clock_->NowTicks(); | 456 event.timestamp = clock_->NowTicks(); |
428 event.type = type; | 457 event.type = type; |
429 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[0]), | 458 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[0]), |
430 packet.size()); | 459 packet.size()); |
431 bool success = reader.Skip(4); | 460 bool success = reader.Skip(4); |
432 uint32_t truncated_rtp_timestamp; | 461 uint32_t truncated_rtp_timestamp; |
433 success &= reader.ReadU32(&truncated_rtp_timestamp); | 462 success &= reader.ReadU32(&truncated_rtp_timestamp); |
434 uint32_t ssrc; | 463 uint32_t ssrc; |
435 success &= reader.ReadU32(&ssrc); | 464 success &= reader.ReadU32(&ssrc); |
436 if (ssrc == audio_ssrc_) { | 465 |
437 event.rtp_timestamp = last_logged_audio_rtp_timestamp_ = | 466 auto it = sessions_.find(ssrc); |
438 last_logged_audio_rtp_timestamp_.Expand(truncated_rtp_timestamp); | 467 // The session should always have been registered in |sessions_|. |
439 event.media_type = AUDIO_EVENT; | 468 DCHECK(it != sessions_.end()); |
440 } else if (ssrc == video_ssrc_) { | 469 event.rtp_timestamp = it->second.last_logged_rtp_timestamp_ = |
441 event.rtp_timestamp = last_logged_video_rtp_timestamp_ = | 470 it->second.last_logged_rtp_timestamp_.Expand(truncated_rtp_timestamp); |
442 last_logged_video_rtp_timestamp_.Expand(truncated_rtp_timestamp); | 471 event.media_type = it->second.is_audio ? AUDIO_EVENT : VIDEO_EVENT; |
443 event.media_type = VIDEO_EVENT; | |
444 } else { | |
445 DVLOG(3) << "Got unknown ssrc " << ssrc << " when logging packet event"; | |
446 return; | |
447 } | |
448 success &= reader.Skip(2); | 472 success &= reader.Skip(2); |
449 success &= reader.ReadU16(&event.packet_id); | 473 success &= reader.ReadU16(&event.packet_id); |
450 success &= reader.ReadU16(&event.max_packet_id); | 474 success &= reader.ReadU16(&event.max_packet_id); |
451 event.size = base::checked_cast<uint32_t>(packet.size()); | 475 event.size = base::checked_cast<uint32_t>(packet.size()); |
452 DCHECK(success); | 476 DCHECK(success); |
453 } | 477 } |
454 | 478 |
455 } // namespace cast | 479 } // namespace cast |
456 } // namespace media | 480 } // namespace media |
OLD | NEW |