Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / media / cast / net / rtp / rtp_sender.cc
blobef1cff70c2c49f6bd138166542f78db3e8d03ca6
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
3 // found in the LICENSE file.
5 #include "media/cast/net/rtp/rtp_sender.h"
7 #include "base/big_endian.h"
8 #include "base/logging.h"
9 #include "base/rand_util.h"
10 #include "media/cast/net/cast_transport_defines.h"
11 #include "media/cast/net/pacing/paced_sender.h"
13 namespace media {
14 namespace cast {
16 namespace {
18 // If there is only one referecne to the packet then copy the
19 // reference and return.
20 // Otherwise return a deep copy of the packet.
21 PacketRef FastCopyPacket(const PacketRef& packet) {
22 if (packet->HasOneRef())
23 return packet;
24 return make_scoped_refptr(new base::RefCountedData<Packet>(packet->data));
27 } // namespace
29 RtpSender::RtpSender(
30 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner,
31 PacedSender* const transport)
32 : transport_(transport),
33 transport_task_runner_(transport_task_runner),
34 weak_factory_(this) {
35 // Randomly set sequence number start value.
36 config_.sequence_number = base::RandInt(0, 65535);
39 RtpSender::~RtpSender() {}
41 bool RtpSender::Initialize(const CastTransportRtpConfig& config) {
42 config_.ssrc = config.ssrc;
43 config_.payload_type = config.rtp_payload_type;
44 packetizer_.reset(new RtpPacketizer(transport_, &storage_, config_));
45 return true;
48 void RtpSender::SendFrame(const EncodedFrame& frame) {
49 DCHECK(packetizer_);
50 packetizer_->SendFrameAsPackets(frame);
51 LOG_IF(DFATAL, storage_.GetNumberOfStoredFrames() > kMaxUnackedFrames)
52 << "Possible bug: Frames are not being actively released from storage.";
55 void RtpSender::ResendPackets(
56 const MissingFramesAndPacketsMap& missing_frames_and_packets,
57 bool cancel_rtx_if_not_in_list, const DedupInfo& dedup_info) {
58 // Iterate over all frames in the list.
59 for (MissingFramesAndPacketsMap::const_iterator it =
60 missing_frames_and_packets.begin();
61 it != missing_frames_and_packets.end();
62 ++it) {
63 SendPacketVector packets_to_resend;
64 uint8 frame_id = it->first;
65 // Set of packets that the receiver wants us to re-send.
66 // If empty, we need to re-send all packets for this frame.
67 const PacketIdSet& missing_packet_set = it->second;
69 bool resend_all = missing_packet_set.find(kRtcpCastAllPacketsLost) !=
70 missing_packet_set.end();
71 bool resend_last = missing_packet_set.find(kRtcpCastLastPacket) !=
72 missing_packet_set.end();
74 const SendPacketVector* stored_packets = storage_.GetFrame8(frame_id);
75 if (!stored_packets)
76 continue;
78 for (SendPacketVector::const_iterator it = stored_packets->begin();
79 it != stored_packets->end(); ++it) {
80 const PacketKey& packet_key = it->first;
81 const uint16 packet_id = packet_key.second.second;
83 // Should we resend the packet?
84 bool resend = resend_all;
86 // Should we resend it because it's in the missing_packet_set?
87 if (!resend &&
88 missing_packet_set.find(packet_id) != missing_packet_set.end()) {
89 resend = true;
92 // If we were asked to resend the last packet, check if it's the
93 // last packet.
94 if (!resend && resend_last && (it + 1) == stored_packets->end()) {
95 resend = true;
98 if (resend) {
99 // Resend packet to the network.
100 VLOG(3) << "Resend " << static_cast<int>(frame_id) << ":"
101 << packet_id;
102 // Set a unique incremental sequence number for every packet.
103 PacketRef packet_copy = FastCopyPacket(it->second);
104 UpdateSequenceNumber(&packet_copy->data);
105 packets_to_resend.push_back(std::make_pair(packet_key, packet_copy));
106 } else if (cancel_rtx_if_not_in_list) {
107 transport_->CancelSendingPacket(it->first);
110 transport_->ResendPackets(packets_to_resend, dedup_info);
114 void RtpSender::CancelSendingFrames(const std::vector<uint32>& frame_ids) {
115 for (std::vector<uint32>::const_iterator i = frame_ids.begin();
116 i != frame_ids.end(); ++i) {
117 const SendPacketVector* stored_packets = storage_.GetFrame8(*i & 0xFF);
118 if (!stored_packets)
119 continue;
120 for (SendPacketVector::const_iterator j = stored_packets->begin();
121 j != stored_packets->end(); ++j) {
122 transport_->CancelSendingPacket(j->first);
124 storage_.ReleaseFrame(*i);
128 void RtpSender::ResendFrameForKickstart(uint32 frame_id,
129 base::TimeDelta dedupe_window) {
130 // Send the last packet of the encoded frame to kick start
131 // retransmission. This gives enough information to the receiver what
132 // packets and frames are missing.
133 MissingFramesAndPacketsMap missing_frames_and_packets;
134 PacketIdSet missing;
135 missing.insert(kRtcpCastLastPacket);
136 missing_frames_and_packets.insert(std::make_pair(frame_id, missing));
138 // Sending this extra packet is to kick-start the session. There is
139 // no need to optimize re-transmission for this case.
140 DedupInfo dedup_info;
141 dedup_info.resend_interval = dedupe_window;
142 ResendPackets(missing_frames_and_packets, false, dedup_info);
145 void RtpSender::UpdateSequenceNumber(Packet* packet) {
146 // TODO(miu): This is an abstraction violation. This needs to be a part of
147 // the overall packet (de)serialization consolidation.
148 static const int kByteOffsetToSequenceNumber = 2;
149 base::BigEndianWriter big_endian_writer(
150 reinterpret_cast<char*>((&packet->front()) + kByteOffsetToSequenceNumber),
151 sizeof(uint16));
152 big_endian_writer.WriteU16(packetizer_->NextSequenceNumber());
155 int64 RtpSender::GetLastByteSentForFrame(uint32 frame_id) {
156 const SendPacketVector* stored_packets = storage_.GetFrame8(frame_id & 0xFF);
157 if (!stored_packets)
158 return 0;
159 PacketKey last_packet_key = stored_packets->rbegin()->first;
160 return transport_->GetLastByteSentForPacket(last_packet_key);
163 } // namespace cast
164 } // namespace media