• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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_sender/rtp_packetizer/rtp_packetizer.h"
6 
7 #include "base/logging.h"
8 #include "media/cast/cast_defines.h"
9 #include "media/cast/net/pacing/paced_sender.h"
10 #include "net/base/big_endian.h"
11 
12 namespace media {
13 namespace cast {
14 
15 static const uint16 kCommonRtpHeaderLength = 12;
16 static const uint16 kCastRtpHeaderLength = 7;
17 static const uint8 kCastKeyFrameBitMask = 0x80;
18 static const uint8 kCastReferenceFrameIdBitMask = 0x40;
19 
RtpPacketizer(PacedPacketSender * transport,PacketStorage * packet_storage,RtpPacketizerConfig rtp_packetizer_config)20 RtpPacketizer::RtpPacketizer(PacedPacketSender* transport,
21                              PacketStorage* packet_storage,
22                              RtpPacketizerConfig rtp_packetizer_config)
23     : config_(rtp_packetizer_config),
24       transport_(transport),
25       packet_storage_(packet_storage),
26       sequence_number_(config_.sequence_number),
27       rtp_timestamp_(config_.rtp_timestamp),
28       packet_id_(0),
29       send_packets_count_(0),
30       send_octet_count_(0) {
31   DCHECK(transport) << "Invalid argument";
32 }
33 
~RtpPacketizer()34 RtpPacketizer::~RtpPacketizer() {}
35 
IncomingEncodedVideoFrame(const EncodedVideoFrame * video_frame,const base::TimeTicks & capture_time)36 void RtpPacketizer::IncomingEncodedVideoFrame(
37     const EncodedVideoFrame* video_frame,
38     const base::TimeTicks& capture_time) {
39   DCHECK(!config_.audio) << "Invalid state";
40   if (config_.audio) return;
41 
42   // Timestamp is in 90 KHz for video.
43   rtp_timestamp_ = GetVideoRtpTimestamp(capture_time);
44   time_last_sent_rtp_timestamp_ = capture_time;
45 
46   Cast(video_frame->key_frame,
47        video_frame->frame_id,
48        video_frame->last_referenced_frame_id,
49        rtp_timestamp_,
50        video_frame->data);
51 }
52 
IncomingEncodedAudioFrame(const EncodedAudioFrame * audio_frame,const base::TimeTicks & recorded_time)53 void RtpPacketizer::IncomingEncodedAudioFrame(
54     const EncodedAudioFrame* audio_frame,
55     const base::TimeTicks& recorded_time) {
56   DCHECK(config_.audio) << "Invalid state";
57   if (!config_.audio) return;
58 
59   rtp_timestamp_ += audio_frame->samples;  // Timestamp is in samples for audio.
60   time_last_sent_rtp_timestamp_ = recorded_time;
61   Cast(true, audio_frame->frame_id, 0, rtp_timestamp_, audio_frame->data);
62 }
63 
NextSequenceNumber()64 uint16 RtpPacketizer::NextSequenceNumber() {
65   ++sequence_number_;
66   return sequence_number_ - 1;
67 }
68 
LastSentTimestamp(base::TimeTicks * time_sent,uint32 * rtp_timestamp) const69 bool RtpPacketizer::LastSentTimestamp(base::TimeTicks* time_sent,
70                                       uint32* rtp_timestamp) const {
71   if (time_last_sent_rtp_timestamp_.is_null()) return false;
72 
73   *time_sent = time_last_sent_rtp_timestamp_;
74   *rtp_timestamp = rtp_timestamp_;
75   return true;
76 }
77 
78 // TODO(mikhal): Switch to pass data with a const_ref.
Cast(bool is_key,uint32 frame_id,uint32 reference_frame_id,uint32 timestamp,const std::string & data)79 void RtpPacketizer::Cast(bool is_key,
80                          uint32 frame_id,
81                          uint32 reference_frame_id,
82                          uint32 timestamp,
83                          const std::string& data) {
84   uint16 rtp_header_length = kCommonRtpHeaderLength + kCastRtpHeaderLength;
85   uint16 max_length = config_.max_payload_length - rtp_header_length - 1;
86 
87   // Split the payload evenly (round number up).
88   size_t num_packets = (data.size() + max_length) / max_length;
89   size_t payload_length = (data.size() + num_packets) / num_packets;
90   DCHECK_LE(payload_length, max_length) << "Invalid argument";
91 
92   PacketList packets;
93 
94   size_t remaining_size = data.size();
95   std::string::const_iterator data_iter = data.begin();
96   while (remaining_size > 0) {
97     Packet packet;
98 
99     if (remaining_size < payload_length) {
100       payload_length = remaining_size;
101     }
102     remaining_size -= payload_length;
103     BuildCommonRTPheader(&packet, remaining_size == 0, timestamp);
104 
105     // Build Cast header.
106     packet.push_back(
107         (is_key ? kCastKeyFrameBitMask : 0) | kCastReferenceFrameIdBitMask);
108     packet.push_back(frame_id);
109     size_t start_size = packet.size();
110     packet.resize(start_size + 4);
111     net::BigEndianWriter big_endian_writer(&(packet[start_size]), 4);
112     big_endian_writer.WriteU16(packet_id_);
113     big_endian_writer.WriteU16(static_cast<uint16>(num_packets - 1));
114     packet.push_back(static_cast<uint8>(reference_frame_id));
115 
116     // Copy payload data.
117     packet.insert(packet.end(), data_iter, data_iter + payload_length);
118 
119     // Store packet.
120     packet_storage_->StorePacket(frame_id, packet_id_, &packet);
121     ++packet_id_;
122     data_iter += payload_length;
123 
124     // Update stats.
125     ++send_packets_count_;
126     send_octet_count_ += payload_length;
127     packets.push_back(packet);
128   }
129   DCHECK(packet_id_ == num_packets) << "Invalid state";
130 
131   // Send to network.
132   transport_->SendPackets(packets);
133 
134   // Prepare for next frame.
135   packet_id_ = 0;
136 }
137 
BuildCommonRTPheader(Packet * packet,bool marker_bit,uint32 time_stamp)138 void RtpPacketizer::BuildCommonRTPheader(
139     Packet* packet, bool marker_bit, uint32 time_stamp) {
140   packet->push_back(0x80);
141   packet->push_back(static_cast<uint8>(config_.payload_type) |
142                     (marker_bit ? kRtpMarkerBitMask : 0));
143   size_t start_size = packet->size();
144   packet->resize(start_size + 10);
145   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10);
146   big_endian_writer.WriteU16(sequence_number_);
147   big_endian_writer.WriteU32(time_stamp);
148   big_endian_writer.WriteU32(config_.ssrc);
149   ++sequence_number_;
150 }
151 
152 }  // namespace cast
153 }  // namespace media
154