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/transport/rtp_sender/rtp_sender.h"
7 #include "base/logging.h"
8 #include "base/rand_util.h"
9 #include "media/cast/transport/cast_transport_defines.h"
10 #include "media/cast/transport/pacing/paced_sender.h"
16 // Schedule the RTP statistics callback every 33mS. As this interval affects the
17 // time offset of the render and playout times, we want it in the same ball park
19 static const int kStatsCallbackIntervalMs = 33;
22 base::TickClock* clock,
24 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner,
25 PacedSender* const transport)
28 transport_(transport),
30 transport_task_runner_(transport_task_runner),
32 // Randomly set sequence number start value.
33 config_.sequence_number = base::RandInt(0, 65535);
36 RtpSender::~RtpSender() {}
38 void RtpSender::InitializeAudio(const CastTransportAudioConfig& config) {
39 storage_.reset(new PacketStorage(clock_, config.base.rtp_config.history_ms));
41 config_.ssrc = config.base.ssrc;
42 config_.payload_type = config.base.rtp_config.payload_type;
43 config_.frequency = config.frequency;
44 config_.audio_codec = config.codec;
46 new RtpPacketizer(transport_, storage_.get(), config_, clock_, logging_));
49 void RtpSender::InitializeVideo(const CastTransportVideoConfig& config) {
50 storage_.reset(new PacketStorage(clock_, config.base.rtp_config.history_ms));
51 config_.audio = false;
52 config_.ssrc = config.base.ssrc;
53 config_.payload_type = config.base.rtp_config.payload_type;
54 config_.frequency = kVideoFrequency;
55 config_.video_codec = config.codec;
57 new RtpPacketizer(transport_, storage_.get(), config_, clock_, logging_));
60 void RtpSender::IncomingEncodedVideoFrame(const EncodedVideoFrame* video_frame,
61 const base::TimeTicks& capture_time) {
63 packetizer_->IncomingEncodedVideoFrame(video_frame, capture_time);
66 void RtpSender::IncomingEncodedAudioFrame(
67 const EncodedAudioFrame* audio_frame,
68 const base::TimeTicks& recorded_time) {
70 packetizer_->IncomingEncodedAudioFrame(audio_frame, recorded_time);
73 void RtpSender::ResendPackets(
74 const MissingFramesAndPacketsMap& missing_frames_and_packets) {
76 // Iterate over all frames in the list.
77 for (MissingFramesAndPacketsMap::const_iterator it =
78 missing_frames_and_packets.begin();
79 it != missing_frames_and_packets.end();
81 PacketList packets_to_resend;
82 uint8 frame_id = it->first;
83 const PacketIdSet& packets_set = it->second;
86 if (packets_set.empty()) {
87 VLOG(3) << "Missing all packets in frame " << static_cast<int>(frame_id);
91 // Get packet from storage.
92 success = storage_->GetPacket(frame_id, packet_id, &packets_to_resend);
94 // Resend packet to the network.
96 VLOG(3) << "Resend " << static_cast<int>(frame_id) << ":"
98 // Set a unique incremental sequence number for every packet.
99 Packet& packet = packets_to_resend.back();
100 UpdateSequenceNumber(&packet);
101 // Set the size as correspond to each frame.
106 // Iterate over all of the packets in the frame.
107 for (PacketIdSet::const_iterator set_it = packets_set.begin();
108 set_it != packets_set.end();
110 uint16 packet_id = *set_it;
111 success = storage_->GetPacket(frame_id, packet_id, &packets_to_resend);
113 // Resend packet to the network.
115 VLOG(3) << "Resend " << static_cast<int>(frame_id) << ":"
117 Packet& packet = packets_to_resend.back();
118 UpdateSequenceNumber(&packet);
122 transport_->ResendPackets(packets_to_resend);
126 void RtpSender::UpdateSequenceNumber(Packet* packet) {
127 uint16 new_sequence_number = packetizer_->NextSequenceNumber();
129 (*packet)[index] = (static_cast<uint8>(new_sequence_number));
130 (*packet)[index + 1] = (static_cast<uint8>(new_sequence_number >> 8));
133 void RtpSender::SubscribeRtpStatsCallback(
134 const CastTransportRtpStatistics& callback) {
135 stats_callback_ = callback;
136 ScheduleNextStatsReport();
139 void RtpSender::ScheduleNextStatsReport() {
140 transport_task_runner_->PostDelayedTask(
142 base::Bind(&RtpSender::RtpStatistics, weak_factory_.GetWeakPtr()),
143 base::TimeDelta::FromMilliseconds(kStatsCallbackIntervalMs));
146 void RtpSender::RtpStatistics() {
147 RtcpSenderInfo sender_info;
148 base::TimeTicks time_sent;
149 uint32 rtp_timestamp = 0;
150 packetizer_->LastSentTimestamp(&time_sent, &rtp_timestamp);
151 sender_info.send_packet_count = packetizer_->send_packets_count();
152 sender_info.send_octet_count = packetizer_->send_octet_count();
153 stats_callback_.Run(sender_info, time_sent, rtp_timestamp);
154 ScheduleNextStatsReport();
157 } // namespace transport