• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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