Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / cast / transport / rtp_sender / rtp_sender.cc
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/transport/rtp_sender/rtp_sender.h"
6
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"
11
12 namespace media {
13 namespace cast {
14 namespace transport {
15
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
18 // as the frame rate.
19 static const int kStatsCallbackIntervalMs = 33;
20
21 RtpSender::RtpSender(
22     base::TickClock* clock,
23     const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner,
24     PacedSender* const transport)
25     : clock_(clock),
26       transport_(transport),
27       stats_callback_(),
28       transport_task_runner_(transport_task_runner),
29       weak_factory_(this) {
30   // Randomly set sequence number start value.
31   config_.sequence_number = base::RandInt(0, 65535);
32 }
33
34 RtpSender::~RtpSender() {}
35
36 bool RtpSender::InitializeAudio(const CastTransportAudioConfig& config) {
37   storage_.reset(new PacketStorage(config.rtp.max_outstanding_frames));
38   if (!storage_->IsValid()) {
39     return false;
40   }
41   config_.audio = true;
42   config_.ssrc = config.rtp.config.ssrc;
43   config_.payload_type = config.rtp.config.payload_type;
44   config_.frequency = config.frequency;
45   config_.audio_codec = config.codec;
46   packetizer_.reset(new RtpPacketizer(transport_, storage_.get(), config_));
47   return true;
48 }
49
50 bool RtpSender::InitializeVideo(const CastTransportVideoConfig& config) {
51   storage_.reset(new PacketStorage(config.rtp.max_outstanding_frames));
52   if (!storage_->IsValid()) {
53     return false;
54   }
55   config_.audio = false;
56   config_.ssrc = config.rtp.config.ssrc;
57   config_.payload_type = config.rtp.config.payload_type;
58   config_.frequency = kVideoFrequency;
59   config_.video_codec = config.codec;
60   packetizer_.reset(new RtpPacketizer(transport_, storage_.get(), config_));
61   return true;
62 }
63
64 void RtpSender::IncomingEncodedVideoFrame(const EncodedVideoFrame* video_frame,
65                                           const base::TimeTicks& capture_time) {
66   DCHECK(packetizer_);
67   packetizer_->IncomingEncodedVideoFrame(video_frame, capture_time);
68 }
69
70 void RtpSender::IncomingEncodedAudioFrame(
71     const EncodedAudioFrame* audio_frame,
72     const base::TimeTicks& recorded_time) {
73   DCHECK(packetizer_);
74   packetizer_->IncomingEncodedAudioFrame(audio_frame, recorded_time);
75 }
76
77 void RtpSender::ResendPackets(
78     const MissingFramesAndPacketsMap& missing_frames_and_packets) {
79   DCHECK(storage_);
80   // Iterate over all frames in the list.
81   for (MissingFramesAndPacketsMap::const_iterator it =
82            missing_frames_and_packets.begin();
83        it != missing_frames_and_packets.end();
84        ++it) {
85     SendPacketVector packets_to_resend;
86     uint8 frame_id = it->first;
87     const PacketIdSet& packets_set = it->second;
88     bool success = false;
89
90     if (packets_set.empty()) {
91       VLOG(3) << "Missing all packets in frame " << static_cast<int>(frame_id);
92
93       uint16 packet_id = 0;
94       do {
95         // Get packet from storage.
96         success = storage_->GetPacket(frame_id, packet_id, &packets_to_resend);
97
98         // Check that we got at least one packet.
99         DCHECK(packet_id != 0 || success)
100             << "Failed to resend frame " << static_cast<int>(frame_id);
101
102         // Resend packet to the network.
103         if (success) {
104           VLOG(3) << "Resend " << static_cast<int>(frame_id) << ":"
105                   << packet_id;
106           // Set a unique incremental sequence number for every packet.
107           PacketRef packet = packets_to_resend.back().second;
108           UpdateSequenceNumber(&packet->data);
109           // Set the size as correspond to each frame.
110           ++packet_id;
111         }
112       } while (success);
113     } else {
114       // Iterate over all of the packets in the frame.
115       for (PacketIdSet::const_iterator set_it = packets_set.begin();
116            set_it != packets_set.end();
117            ++set_it) {
118         uint16 packet_id = *set_it;
119         success = storage_->GetPacket(frame_id, packet_id, &packets_to_resend);
120
121         // Check that we got at least one packet.
122         DCHECK(set_it != packets_set.begin() || success)
123             << "Failed to resend frame " << frame_id;
124
125         // Resend packet to the network.
126         if (success) {
127           VLOG(3) << "Resend " << static_cast<int>(frame_id) << ":"
128                   << packet_id;
129           PacketRef packet = packets_to_resend.back().second;
130           UpdateSequenceNumber(&packet->data);
131         }
132       }
133     }
134     transport_->ResendPackets(packets_to_resend);
135   }
136 }
137
138 void RtpSender::UpdateSequenceNumber(Packet* packet) {
139   uint16 new_sequence_number = packetizer_->NextSequenceNumber();
140   int index = 2;
141   (*packet)[index] = (static_cast<uint8>(new_sequence_number));
142   (*packet)[index + 1] = (static_cast<uint8>(new_sequence_number >> 8));
143 }
144
145 void RtpSender::SubscribeRtpStatsCallback(
146     const CastTransportRtpStatistics& callback) {
147   stats_callback_ = callback;
148   ScheduleNextStatsReport();
149 }
150
151 void RtpSender::ScheduleNextStatsReport() {
152   transport_task_runner_->PostDelayedTask(
153       FROM_HERE,
154       base::Bind(&RtpSender::RtpStatistics, weak_factory_.GetWeakPtr()),
155       base::TimeDelta::FromMilliseconds(kStatsCallbackIntervalMs));
156 }
157
158 void RtpSender::RtpStatistics() {
159   RtcpSenderInfo sender_info;
160   base::TimeTicks time_sent;
161   uint32 rtp_timestamp = 0;
162   packetizer_->LastSentTimestamp(&time_sent, &rtp_timestamp);
163   sender_info.send_packet_count = packetizer_->send_packets_count();
164   sender_info.send_octet_count = packetizer_->send_octet_count();
165   stats_callback_.Run(sender_info, time_sent, rtp_timestamp);
166   ScheduleNextStatsReport();
167 }
168
169 }  // namespace transport
170 }  //  namespace cast
171 }  // namespace media