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.
5 #include "media/cast/rtp_sender/rtp_packetizer/rtp_packetizer.h"
7 #include "base/logging.h"
8 #include "media/cast/cast_defines.h"
9 #include "media/cast/pacing/paced_sender.h"
10 #include "net/base/big_endian.h"
15 static const uint16 kCommonRtpHeaderLength = 12;
16 static const uint16 kCastRtpHeaderLength = 7;
17 static const uint8 kCastKeyFrameBitMask = 0x80;
18 static const uint8 kCastReferenceFrameIdBitMask = 0x40;
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),
30 send_packets_count_(0),
31 send_octet_count_(0) {
32 DCHECK(transport) << "Invalid argument";
35 RtpPacketizer::~RtpPacketizer() {}
37 void RtpPacketizer::IncomingEncodedVideoFrame(
38 const EncodedVideoFrame* video_frame,
39 const base::TimeTicks& capture_time) {
40 DCHECK(!config_.audio) << "Invalid state";
41 if (config_.audio) return;
43 base::TimeTicks zero_time;
44 base::TimeDelta capture_delta = capture_time - zero_time;
46 // Timestamp is in 90 KHz for video.
47 rtp_timestamp_ = static_cast<uint32>(capture_delta.InMilliseconds() * 90);
48 time_last_sent_rtp_timestamp_ = capture_time;
50 Cast(video_frame->key_frame,
51 video_frame->last_referenced_frame_id,
56 void RtpPacketizer::IncomingEncodedAudioFrame(
57 const EncodedAudioFrame* audio_frame,
58 const base::TimeTicks& recorded_time) {
59 DCHECK(config_.audio) << "Invalid state";
60 if (!config_.audio) return;
62 rtp_timestamp_ += audio_frame->samples; // Timestamp is in samples for audio.
63 time_last_sent_rtp_timestamp_ = recorded_time;
64 Cast(true, 0, rtp_timestamp_, audio_frame->data);
67 uint16 RtpPacketizer::NextSequenceNumber() {
69 return sequence_number_ - 1;
72 bool RtpPacketizer::LastSentTimestamp(base::TimeTicks* time_sent,
73 uint32* rtp_timestamp) const {
74 if (time_last_sent_rtp_timestamp_.is_null()) return false;
76 *time_sent = time_last_sent_rtp_timestamp_;
77 *rtp_timestamp = rtp_timestamp_;
81 void RtpPacketizer::Cast(bool is_key,
82 uint8 reference_frame_id,
85 uint16 rtp_header_length = kCommonRtpHeaderLength + kCastRtpHeaderLength;
86 uint16 max_length = config_.max_payload_length - rtp_header_length - 1;
88 // Split the payload evenly (round number up).
89 size_t num_packets = (data.size() + max_length) / max_length;
90 size_t payload_length = (data.size() + num_packets) / num_packets;
91 DCHECK_LE(payload_length, max_length) << "Invalid argument";
95 size_t remaining_size = data.size();
96 Packet::iterator data_iter = data.begin();
97 while (remaining_size > 0) {
100 if (remaining_size < payload_length) {
101 payload_length = remaining_size;
103 remaining_size -= payload_length;
104 BuildCommonRTPheader(&packet, remaining_size == 0, timestamp);
106 // Build Cast header.
108 (is_key ? kCastKeyFrameBitMask : 0) | kCastReferenceFrameIdBitMask);
109 packet.push_back(frame_id_);
110 size_t start_size = packet.size();
111 packet.resize(start_size + 4);
112 net::BigEndianWriter big_endian_writer(&(packet[start_size]), 4);
113 big_endian_writer.WriteU16(packet_id_);
114 big_endian_writer.WriteU16(static_cast<uint16>(num_packets - 1));
115 packet.push_back(reference_frame_id);
117 // Copy payload data.
118 packet.insert(packet.end(), data_iter, data_iter + payload_length);
121 packet_storage_->StorePacket(frame_id_, packet_id_, &packet);
123 data_iter += payload_length;
126 ++send_packets_count_;
127 send_octet_count_ += payload_length;
128 packets.push_back(packet);
130 DCHECK(packet_id_ == num_packets) << "Invalid state";
133 transport_->SendPackets(packets);
135 // Prepare for next frame.
137 frame_id_ = static_cast<uint8>(frame_id_ + 1);
140 void RtpPacketizer::BuildCommonRTPheader(
141 Packet* packet, bool marker_bit, uint32 time_stamp) {
142 packet->push_back(0x80);
143 packet->push_back(static_cast<uint8>(config_.payload_type) |
144 (marker_bit ? kRtpMarkerBitMask : 0));
145 size_t start_size = packet->size();
146 packet->resize(start_size + 10);
147 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10);
148 big_endian_writer.WriteU16(sequence_number_);
149 big_endian_writer.WriteU32(time_stamp);
150 big_endian_writer.WriteU32(config_.ssrc);