Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 for (size_t i = 0; i < packets.size(); i++) { | 66 for (size_t i = 0; i < packets.size(); i++) { |
| 67 packet_list_[packets[i].first] = | 67 packet_list_[packets[i].first] = |
| 68 make_pair(PacketType_Normal, packets[i].second); | 68 make_pair(PacketType_Normal, packets[i].second); |
| 69 } | 69 } |
| 70 if (state_ == State_Unblocked) { | 70 if (state_ == State_Unblocked) { |
| 71 SendStoredPackets(); | 71 SendStoredPackets(); |
| 72 } | 72 } |
| 73 return true; | 73 return true; |
| 74 } | 74 } |
| 75 | 75 |
| 76 bool PacedSender::ResendPackets(const SendPacketVector& packets) { | 76 bool PacedSender::ResendPackets(const SendPacketVector& packets, |
| 77 base::TimeDelta rtt) { | |
| 78 VLOG(0) << "RESENDPACKETS!!!!!!!"; | |
|
Alpha Left Google
2014/06/18 01:43:32
This shouldn't be there.
hubbe
2014/06/18 20:22:28
Already gone.
| |
| 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 < rtt) { | |
| 88 // TODO(hubbe): Log this. | |
|
Alpha Left Google
2014/06/18 01:43:32
We should log a PACKET_RTX_REJECTED event in the l
hubbe
2014/06/18 20:22:28
Done.
| |
| 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 Loading... | |
| 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 { |
| 126 return packet_list_.size(); | 139 return packet_list_.size(); |
| 127 } | 140 } |
| 128 | 141 |
| 129 // This function can be called from three places: | 142 // This function can be called from three places: |
| 130 // 1. User called one of the Send* functions and we were in an unblocked state. | 143 // 1. User called one of the Send* functions and we were in an unblocked state. |
| 131 // 2. state_ == State_TransportBlocked and the transport is calling us to | 144 // 2. state_ == State_TransportBlocked and the transport is calling us to |
| 132 // let us know that it's ok to send again. | 145 // let us know that it's ok to send again. |
| 133 // 3. state_ == State_BurstFull and there are still packets to send. In this | 146 // 3. state_ == State_BurstFull and there are still packets to send. In this |
| 134 // case we called PostDelayedTask on this function to start a new burst. | 147 // case we called PostDelayedTask on this function to start a new burst. |
| 135 void PacedSender::SendStoredPackets() { | 148 void PacedSender::SendStoredPackets() { |
| 136 State previous_state = state_; | 149 State previous_state = state_; |
| 150 | |
| 151 if (state_ == State_TransportBlocked) { | |
| 152 base::TimeTicks sent_time = clock_->NowTicks(); | |
| 153 sent_time_[in_progress_packet_key_] = sent_time; | |
| 154 sent_time_buffer_[in_progress_packet_key_] = sent_time; | |
| 155 } | |
| 156 | |
| 137 state_ = State_Unblocked; | 157 state_ = State_Unblocked; |
| 138 if (empty()) { | 158 if (empty()) { |
| 139 return; | 159 return; |
| 140 } | 160 } |
| 141 | 161 |
| 142 base::TimeTicks now = clock_->NowTicks(); | 162 base::TimeTicks now = clock_->NowTicks(); |
| 143 // I don't actually trust that PostDelayTask(x - now) will mean that | 163 // I don't actually trust that PostDelayTask(x - now) will mean that |
| 144 // now >= x when the call happens, so check if the previous state was | 164 // now >= x when the call happens, so check if the previous state was |
| 145 // State_BurstFull too. | 165 // State_BurstFull too. |
| 146 if (now >= burst_end_ || previous_state == State_BurstFull) { | 166 if (now >= burst_end_ || previous_state == State_BurstFull) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 weak_factory_.GetWeakPtr()); | 198 weak_factory_.GetWeakPtr()); |
| 179 while (!empty()) { | 199 while (!empty()) { |
| 180 if (current_burst_size_ >= max_burst_size_) { | 200 if (current_burst_size_ >= max_burst_size_) { |
| 181 transport_task_runner_->PostDelayedTask(FROM_HERE, | 201 transport_task_runner_->PostDelayedTask(FROM_HERE, |
| 182 cb, | 202 cb, |
| 183 burst_end_ - now); | 203 burst_end_ - now); |
| 184 state_ = State_BurstFull; | 204 state_ = State_BurstFull; |
| 185 return; | 205 return; |
| 186 } | 206 } |
| 187 PacketType packet_type; | 207 PacketType packet_type; |
| 188 PacketRef packet = GetNextPacket(&packet_type); | 208 PacketRef packet = GetNextPacket(&packet_type, |
| 209 &in_progress_packet_key_); | |
| 189 | 210 |
| 190 switch (packet_type) { | 211 switch (packet_type) { |
| 191 case PacketType_Resend: | 212 case PacketType_Resend: |
| 192 LogPacketEvent(packet->data, true); | 213 LogPacketEvent(packet->data, true); |
| 193 break; | 214 break; |
| 194 case PacketType_Normal: | 215 case PacketType_Normal: |
| 195 LogPacketEvent(packet->data, false); | 216 LogPacketEvent(packet->data, false); |
| 196 break; | 217 break; |
| 197 case PacketType_RTCP: | 218 case PacketType_RTCP: |
| 198 break; | 219 break; |
| 199 } | 220 } |
| 200 if (!transport_->SendPacket(packet, cb)) { | 221 if (!transport_->SendPacket(packet, cb)) { |
| 201 state_ = State_TransportBlocked; | 222 state_ = State_TransportBlocked; |
| 202 return; | 223 return; |
| 203 } | 224 } |
| 204 current_burst_size_++; | 225 current_burst_size_++; |
| 226 base::TimeTicks sent_time = clock_->NowTicks(); | |
| 227 sent_time_[in_progress_packet_key_] = sent_time; | |
| 228 sent_time_buffer_[in_progress_packet_key_] = sent_time; | |
| 229 } | |
| 230 // Keep ~1 second of data (1000 packets) | |
| 231 if (sent_time_buffer_.size() > kMaxBurstSize * 1000 / kPacingIntervalMs) { | |
|
Alpha Left Google
2014/06/18 01:43:32
nit: Define 1000 as a constant at the top of this
hubbe
2014/06/18 20:22:27
It's just the number of milliseconds in a second.
| |
| 232 sent_time_.swap(sent_time_buffer_); | |
| 233 sent_time_buffer_.clear(); | |
| 205 } | 234 } |
| 206 state_ = State_Unblocked; | 235 state_ = State_Unblocked; |
|
Alpha Left Google
2014/06/18 01:43:32
Please put a DCHECK for the sizes of the sent_time
hubbe
2014/06/18 20:22:27
Done.
| |
| 207 } | 236 } |
| 208 | 237 |
| 209 void PacedSender::LogPacketEvent(const Packet& packet, bool retransmit) { | 238 void PacedSender::LogPacketEvent(const Packet& packet, bool retransmit) { |
| 210 // Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see | 239 // Get SSRC from packet and compare with the audio_ssrc / video_ssrc to see |
| 211 // if the packet is audio or video. | 240 // if the packet is audio or video. |
| 212 DCHECK_GE(packet.size(), 12u); | 241 DCHECK_GE(packet.size(), 12u); |
| 213 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[8]), 4); | 242 base::BigEndianReader reader(reinterpret_cast<const char*>(&packet[8]), 4); |
| 214 uint32 ssrc; | 243 uint32 ssrc; |
| 215 bool success = reader.ReadU32(&ssrc); | 244 bool success = reader.ReadU32(&ssrc); |
| 216 DCHECK(success); | 245 DCHECK(success); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 227 CastLoggingEvent event = retransmit ? | 256 CastLoggingEvent event = retransmit ? |
| 228 PACKET_RETRANSMITTED : PACKET_SENT_TO_NETWORK; | 257 PACKET_RETRANSMITTED : PACKET_SENT_TO_NETWORK; |
| 229 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; | 258 EventMediaType media_type = is_audio ? AUDIO_EVENT : VIDEO_EVENT; |
| 230 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, | 259 logging_->InsertSinglePacketEvent(clock_->NowTicks(), event, media_type, |
| 231 packet); | 260 packet); |
| 232 } | 261 } |
| 233 | 262 |
| 234 } // namespace transport | 263 } // namespace transport |
| 235 } // namespace cast | 264 } // namespace cast |
| 236 } // namespace media | 265 } // namespace media |
| OLD | NEW |