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"
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())
24 return make_scoped_refptr(new base::RefCountedData
<Packet
>(packet
->data
));
30 const scoped_refptr
<base::SingleThreadTaskRunner
>& transport_task_runner
,
31 PacedSender
* const transport
)
32 : transport_(transport
),
33 transport_task_runner_(transport_task_runner
),
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_
));
48 void RtpSender::SendFrame(const EncodedFrame
& frame
) {
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();
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
);
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?
88 missing_packet_set
.find(packet_id
) != missing_packet_set
.end()) {
92 // If we were asked to resend the last packet, check if it's the
94 if (!resend
&& resend_last
&& (it
+ 1) == stored_packets
->end()) {
99 // Resend packet to the network.
100 VLOG(3) << "Resend " << static_cast<int>(frame_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);
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
;
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
),
152 big_endian_writer
.WriteU16(packetizer_
->NextSequenceNumber());
155 int64
RtpSender::GetLastByteSentForFrame(uint32 frame_id
) {
156 const SendPacketVector
* stored_packets
= storage_
.GetFrame8(frame_id
& 0xFF);
159 PacketKey last_packet_key
= stored_packets
->rbegin()->first
;
160 return transport_
->GetLastByteSentForPacket(last_packet_key
);