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.
4
5 #include "media/cast/net/rtp/rtp_packetizer.h"
6
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"
11
12 namespace media {
13 namespace cast {
14
RtpPacketizerConfig()15 RtpPacketizerConfig::RtpPacketizerConfig()
16 : payload_type(-1),
17 max_payload_length(kMaxIpPacketSize - 28), // Default is IP-v4/UDP.
18 sequence_number(0),
19 ssrc(0) {}
20
~RtpPacketizerConfig()21 RtpPacketizerConfig::~RtpPacketizerConfig() {}
22
RtpPacketizer(PacedSender * const transport,PacketStorage * packet_storage,RtpPacketizerConfig rtp_packetizer_config)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),
30 rtp_timestamp_(0),
31 packet_id_(0),
32 send_packet_count_(0),
33 send_octet_count_(0) {
34 DCHECK(transport) << "Invalid argument";
35 }
36
~RtpPacketizer()37 RtpPacketizer::~RtpPacketizer() {}
38
NextSequenceNumber()39 uint16 RtpPacketizer::NextSequenceNumber() {
40 ++sequence_number_;
41 return sequence_number_ - 1;
42 }
43
SendFrameAsPackets(const EncodedFrame & frame)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;
48
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";
53
54 SendPacketVector packets;
55
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>);
60
61 if (remaining_size < payload_length) {
62 payload_length = remaining_size;
63 }
64 remaining_size -= payload_length;
65 BuildCommonRTPheader(
66 &packet->data, remaining_size == 0, frame.rtp_timestamp);
67
68 // Build Cast header.
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)
73 num_extensions++;
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));
95 }
96
97 // Copy payload data.
98 packet->data.insert(packet->data.end(),
99 data_iter,
100 data_iter + payload_length);
101 data_iter += payload_length;
102
103 const PacketKey key =
104 PacedPacketSender::MakePacketKey(frame.reference_time,
105 config_.ssrc,
106 packet_id_++);
107 packets.push_back(make_pair(key, packet));
108
109 // Update stats.
110 ++send_packet_count_;
111 send_octet_count_ += payload_length;
112 }
113 DCHECK(packet_id_ == num_packets) << "Invalid state";
114
115 packet_storage_->StoreFrame(frame.frame_id, packets);
116
117 // Send to network.
118 transport_->SendPackets(packets);
119
120 // Prepare for next frame.
121 packet_id_ = 0;
122 }
123
BuildCommonRTPheader(Packet * packet,bool marker_bit,uint32 time_stamp)124 void RtpPacketizer::BuildCommonRTPheader(Packet* packet,
125 bool marker_bit,
126 uint32 time_stamp) {
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);
137 ++sequence_number_;
138 }
139
140 } // namespace cast
141 } // namespace media
142