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
3 // found in the LICENSE file.
5 #include "media/cast/pacing/paced_sender.h"
8 #include "base/message_loop/message_loop.h"
13 static const int64 kPacingIntervalMs
= 10;
14 // Each frame will be split into no more than kPacingMaxBurstsPerFrame
16 static const size_t kPacingMaxBurstsPerFrame
= 3;
18 PacedSender::PacedSender(scoped_refptr
<CastEnvironment
> cast_environment
,
19 PacketSender
* transport
)
20 : cast_environment_(cast_environment
),
22 packets_sent_in_burst_(0),
23 transport_(transport
),
28 PacedSender::~PacedSender() {}
30 bool PacedSender::SendPackets(const PacketList
& packets
) {
31 return SendPacketsToTransport(packets
, &packet_list_
);
34 bool PacedSender::ResendPackets(const PacketList
& packets
) {
35 return SendPacketsToTransport(packets
, &resend_packet_list_
);
38 bool PacedSender::SendPacketsToTransport(const PacketList
& packets
,
39 PacketList
* packets_not_sent
) {
40 UpdateBurstSize(packets
.size());
42 if (!packets_not_sent
->empty()) {
43 packets_not_sent
->insert(packets_not_sent
->end(),
44 packets
.begin(), packets
.end());
47 PacketList packets_to_send
;
48 PacketList::const_iterator first_to_store_it
= packets
.begin();
50 size_t max_packets_to_send_now
= burst_size_
- packets_sent_in_burst_
;
51 if (max_packets_to_send_now
> 0) {
52 size_t packets_to_send_now
= std::min(max_packets_to_send_now
,
55 std::advance(first_to_store_it
, packets_to_send_now
);
56 packets_to_send
.insert(packets_to_send
.begin(),
57 packets
.begin(), first_to_store_it
);
59 packets_not_sent
->insert(packets_not_sent
->end(),
60 first_to_store_it
, packets
.end());
61 packets_sent_in_burst_
+= packets_to_send
.size();
62 if (packets_to_send
.empty()) return true;
64 return transport_
->SendPackets(packets_to_send
);
67 bool PacedSender::SendRtcpPacket(const Packet
& packet
) {
68 // We pass the RTCP packets straight through.
69 return transport_
->SendPacket(packet
);
72 void PacedSender::ScheduleNextSend() {
73 base::TimeDelta time_to_next
= time_last_process_
-
74 cast_environment_
->Clock()->NowTicks() +
75 base::TimeDelta::FromMilliseconds(kPacingIntervalMs
);
77 time_to_next
= std::max(time_to_next
, base::TimeDelta());
79 cast_environment_
->PostDelayedTask(CastEnvironment::MAIN
, FROM_HERE
,
80 base::Bind(&PacedSender::SendNextPacketBurst
, weak_factory_
.GetWeakPtr()),
84 void PacedSender::SendNextPacketBurst() {
86 time_last_process_
= cast_environment_
->Clock()->NowTicks();
90 void PacedSender::SendStoredPackets() {
91 if (packet_list_
.empty() && resend_packet_list_
.empty()) return;
93 size_t packets_to_send
= burst_size_
;
94 PacketList packets_to_resend
;
96 // Send our re-send packets first.
97 if (!resend_packet_list_
.empty()) {
98 PacketList::iterator it
= resend_packet_list_
.begin();
99 size_t packets_to_send_now
= std::min(packets_to_send
,
100 resend_packet_list_
.size());
101 std::advance(it
, packets_to_send_now
);
102 packets_to_resend
.insert(packets_to_resend
.begin(),
103 resend_packet_list_
.begin(), it
);
104 resend_packet_list_
.erase(resend_packet_list_
.begin(), it
);
105 packets_to_send
-= packets_to_resend
.size();
107 if (!packet_list_
.empty() && packets_to_send
> 0) {
108 PacketList::iterator it
= packet_list_
.begin();
109 size_t packets_to_send_now
= std::min(packets_to_send
,
110 packet_list_
.size());
112 std::advance(it
, packets_to_send_now
);
113 packets_to_resend
.insert(packets_to_resend
.end(),
114 packet_list_
.begin(), it
);
115 packet_list_
.erase(packet_list_
.begin(), it
);
117 if (packet_list_
.empty()) {
118 burst_size_
= 1; // Reset burst size after we sent the last stored packet
119 packets_sent_in_burst_
= 0;
122 transport_
->SendPackets(packets_to_resend
);
125 void PacedSender::UpdateBurstSize(size_t packets_to_send
) {
126 packets_to_send
= std::max(packets_to_send
,
127 resend_packet_list_
.size() + packet_list_
.size());
129 packets_to_send
+= (kPacingMaxBurstsPerFrame
- 1); // Round up.
130 burst_size_
= std::max(packets_to_send
/ kPacingMaxBurstsPerFrame
,