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"
16 // If there is only one referecne to the packet then copy the
17 // reference and return.
18 // Otherwise return a deep copy of the packet.
19 PacketRef
FastCopyPacket(const PacketRef
& packet
) {
20 if (packet
->HasOneRef())
22 return make_scoped_refptr(new base::RefCountedData
<Packet
>(packet
->data
));
28 const scoped_refptr
<base::SingleThreadTaskRunner
>& transport_task_runner
,
29 PacedSender
* const transport
)
30 : transport_(transport
),
31 transport_task_runner_(transport_task_runner
),
33 // Randomly set sequence number start value.
34 config_
.sequence_number
= base::RandInt(0, 65535);
37 RtpSender::~RtpSender() {}
39 bool RtpSender::Initialize(const CastTransportRtpConfig
& config
) {
40 config_
.ssrc
= config
.ssrc
;
41 config_
.payload_type
= config
.rtp_payload_type
;
42 packetizer_
.reset(new RtpPacketizer(transport_
, &storage_
, config_
));
46 void RtpSender::SendFrame(const EncodedFrame
& frame
) {
48 packetizer_
->SendFrameAsPackets(frame
);
49 LOG_IF(DFATAL
, storage_
.GetNumberOfStoredFrames() > kMaxUnackedFrames
)
50 << "Possible bug: Frames are not being actively released from storage.";
53 void RtpSender::ResendPackets(
54 const MissingFramesAndPacketsMap
& missing_frames_and_packets
,
55 bool cancel_rtx_if_not_in_list
, const DedupInfo
& dedup_info
) {
56 // Iterate over all frames in the list.
57 for (MissingFramesAndPacketsMap::const_iterator it
=
58 missing_frames_and_packets
.begin();
59 it
!= missing_frames_and_packets
.end();
61 SendPacketVector packets_to_resend
;
62 uint8 frame_id
= it
->first
;
63 // Set of packets that the receiver wants us to re-send.
64 // If empty, we need to re-send all packets for this frame.
65 const PacketIdSet
& missing_packet_set
= it
->second
;
67 bool resend_all
= missing_packet_set
.find(kRtcpCastAllPacketsLost
) !=
68 missing_packet_set
.end();
69 bool resend_last
= missing_packet_set
.find(kRtcpCastLastPacket
) !=
70 missing_packet_set
.end();
72 const SendPacketVector
* stored_packets
= storage_
.GetFrame8(frame_id
);
76 for (SendPacketVector::const_iterator it
= stored_packets
->begin();
77 it
!= stored_packets
->end(); ++it
) {
78 const PacketKey
& packet_key
= it
->first
;
79 const uint16 packet_id
= packet_key
.second
.second
;
81 // Should we resend the packet?
82 bool resend
= resend_all
;
84 // Should we resend it because it's in the missing_packet_set?
86 missing_packet_set
.find(packet_id
) != missing_packet_set
.end()) {
90 // If we were asked to resend the last packet, check if it's the
92 if (!resend
&& resend_last
&& (it
+ 1) == stored_packets
->end()) {
97 // Resend packet to the network.
98 VLOG(3) << "Resend " << static_cast<int>(frame_id
) << ":"
100 // Set a unique incremental sequence number for every packet.
101 PacketRef packet_copy
= FastCopyPacket(it
->second
);
102 UpdateSequenceNumber(&packet_copy
->data
);
103 packets_to_resend
.push_back(std::make_pair(packet_key
, packet_copy
));
104 } else if (cancel_rtx_if_not_in_list
) {
105 transport_
->CancelSendingPacket(it
->first
);
108 transport_
->ResendPackets(packets_to_resend
, dedup_info
);
112 void RtpSender::CancelSendingFrames(const std::vector
<uint32
>& frame_ids
) {
113 for (std::vector
<uint32
>::const_iterator i
= frame_ids
.begin();
114 i
!= frame_ids
.end(); ++i
) {
115 const SendPacketVector
* stored_packets
= storage_
.GetFrame8(*i
& 0xFF);
118 for (SendPacketVector::const_iterator j
= stored_packets
->begin();
119 j
!= stored_packets
->end(); ++j
) {
120 transport_
->CancelSendingPacket(j
->first
);
122 storage_
.ReleaseFrame(*i
);
126 void RtpSender::ResendFrameForKickstart(uint32 frame_id
,
127 base::TimeDelta dedupe_window
) {
128 // Send the last packet of the encoded frame to kick start
129 // retransmission. This gives enough information to the receiver what
130 // packets and frames are missing.
131 MissingFramesAndPacketsMap missing_frames_and_packets
;
133 missing
.insert(kRtcpCastLastPacket
);
134 missing_frames_and_packets
.insert(std::make_pair(frame_id
, missing
));
136 // Sending this extra packet is to kick-start the session. There is
137 // no need to optimize re-transmission for this case.
138 DedupInfo dedup_info
;
139 dedup_info
.resend_interval
= dedupe_window
;
140 ResendPackets(missing_frames_and_packets
, false, dedup_info
);
143 void RtpSender::UpdateSequenceNumber(Packet
* packet
) {
144 // TODO(miu): This is an abstraction violation. This needs to be a part of
145 // the overall packet (de)serialization consolidation.
146 static const int kByteOffsetToSequenceNumber
= 2;
147 base::BigEndianWriter
big_endian_writer(
148 reinterpret_cast<char*>((&packet
->front()) + kByteOffsetToSequenceNumber
),
150 big_endian_writer
.WriteU16(packetizer_
->NextSequenceNumber());
153 int64
RtpSender::GetLastByteSentForFrame(uint32 frame_id
) {
154 const SendPacketVector
* stored_packets
= storage_
.GetFrame8(frame_id
& 0xFF);
157 PacketKey last_packet_key
= stored_packets
->rbegin()->first
;
158 return transport_
->GetLastByteSentForPacket(last_packet_key
);