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_packetizer.h"
7 #include "base/big_endian.h"
8 #include "base/logging.h"
9 #include "media/cast/net/pacing/paced_sender.h"
10 #include "media/cast/net/rtp/rtp_defines.h"
15 RtpPacketizerConfig::RtpPacketizerConfig()
17 max_payload_length(kMaxIpPacketSize
- 28), // Default is IP-v4/UDP.
21 RtpPacketizerConfig::~RtpPacketizerConfig() {}
23 RtpPacketizer::RtpPacketizer(PacedSender
* const transport
,
24 PacketStorage
* packet_storage
,
25 RtpPacketizerConfig rtp_packetizer_config
)
26 : config_(rtp_packetizer_config
),
27 transport_(transport
),
28 packet_storage_(packet_storage
),
29 sequence_number_(config_
.sequence_number
),
32 send_packet_count_(0),
33 send_octet_count_(0) {
34 DCHECK(transport
) << "Invalid argument";
37 RtpPacketizer::~RtpPacketizer() {}
39 uint16
RtpPacketizer::NextSequenceNumber() {
41 return sequence_number_
- 1;
44 void RtpPacketizer::SendFrameAsPackets(const EncodedFrame
& frame
) {
45 uint16 rtp_header_length
= kRtpHeaderLength
+ kCastHeaderLength
;
46 uint16 max_length
= config_
.max_payload_length
- rtp_header_length
- 1;
47 rtp_timestamp_
= frame
.rtp_timestamp
;
49 // Split the payload evenly (round number up).
50 size_t num_packets
= (frame
.data
.size() + max_length
) / max_length
;
51 size_t payload_length
= (frame
.data
.size() + num_packets
) / num_packets
;
52 DCHECK_LE(payload_length
, max_length
) << "Invalid argument";
54 SendPacketVector packets
;
56 size_t remaining_size
= frame
.data
.size();
57 std::string::const_iterator data_iter
= frame
.data
.begin();
58 while (remaining_size
> 0) {
59 PacketRef
packet(new base::RefCountedData
<Packet
>);
61 if (remaining_size
< payload_length
) {
62 payload_length
= remaining_size
;
64 remaining_size
-= payload_length
;
66 &packet
->data
, remaining_size
== 0, frame
.rtp_timestamp
);
69 // TODO(miu): Should we always set the ref frame bit and the ref_frame_id?
70 DCHECK_NE(frame
.dependency
, EncodedFrame::UNKNOWN_DEPENDENCY
);
71 uint8 num_extensions
= 0;
72 if (frame
.new_playout_delay_ms
)
74 uint8 byte0
= kCastReferenceFrameIdBitMask
;
75 if (frame
.dependency
== EncodedFrame::KEY
)
76 byte0
|= kCastKeyFrameBitMask
;
77 DCHECK_LE(num_extensions
, kCastExtensionCountmask
);
78 byte0
|= num_extensions
;
79 packet
->data
.push_back(byte0
);
80 packet
->data
.push_back(static_cast<uint8
>(frame
.frame_id
));
81 size_t start_size
= packet
->data
.size();
82 packet
->data
.resize(start_size
+ 4);
83 base::BigEndianWriter
big_endian_writer(
84 reinterpret_cast<char*>(&(packet
->data
[start_size
])), 4);
85 big_endian_writer
.WriteU16(packet_id_
);
86 big_endian_writer
.WriteU16(static_cast<uint16
>(num_packets
- 1));
87 packet
->data
.push_back(static_cast<uint8
>(frame
.referenced_frame_id
));
88 if (frame
.new_playout_delay_ms
) {
89 packet
->data
.push_back(kCastRtpExtensionAdaptiveLatency
<< 2);
90 packet
->data
.push_back(2); // 2 bytes
91 packet
->data
.push_back(
92 static_cast<uint8
>(frame
.new_playout_delay_ms
>> 8));
93 packet
->data
.push_back(
94 static_cast<uint8
>(frame
.new_playout_delay_ms
));
98 packet
->data
.insert(packet
->data
.end(),
100 data_iter
+ payload_length
);
101 data_iter
+= payload_length
;
103 const PacketKey key
=
104 PacedPacketSender::MakePacketKey(frame
.reference_time
,
107 packets
.push_back(make_pair(key
, packet
));
110 ++send_packet_count_
;
111 send_octet_count_
+= payload_length
;
113 DCHECK(packet_id_
== num_packets
) << "Invalid state";
115 packet_storage_
->StoreFrame(frame
.frame_id
, packets
);
118 transport_
->SendPackets(packets
);
120 // Prepare for next frame.
124 void RtpPacketizer::BuildCommonRTPheader(Packet
* packet
,
127 packet
->push_back(0x80);
128 packet
->push_back(static_cast<uint8
>(config_
.payload_type
) |
129 (marker_bit
? kRtpMarkerBitMask
: 0));
130 size_t start_size
= packet
->size();
131 packet
->resize(start_size
+ 10);
132 base::BigEndianWriter
big_endian_writer(
133 reinterpret_cast<char*>(&((*packet
)[start_size
])), 10);
134 big_endian_writer
.WriteU16(sequence_number_
);
135 big_endian_writer
.WriteU32(time_stamp
);
136 big_endian_writer
.WriteU32(config_
.ssrc
);