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 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 34 RtpPacketizer::~RtpPacketizer() {} 35 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 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 64 uint16 RtpPacketizer::NextSequenceNumber() { 65 ++sequence_number_; 66 return sequence_number_ - 1; 67 } 68 69 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. 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 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