Upstream version 5.34.104.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 #include "net/base/big_endian.h"
12
13 namespace media {
14 namespace cast {
15 namespace transport {
16
17 // Schedule the RTP statistics callback every 33mS. As this interval affects the
18 // time offset of the render and playout times, we want it in the same ball park
19 // as the frame rate.
20 static const int kStatsCallbackIntervalMs = 33;
21
22 RtpSender::RtpSender(
23     base::TickClock* clock,
24     const CastTransportConfig& config,
25     bool is_audio,
26     const scoped_refptr<base::TaskRunner>& transport_task_runner,
27     PacedSender* const transport)
28     : config_(),
29       transport_(transport),
30       stats_callback_(),
31       transport_task_runner_(transport_task_runner) {
32   // Store generic cast config and create packetizer config.
33   if (is_audio) {
34     storage_.reset(
35         new PacketStorage(clock, config.audio_rtp_config.history_ms));
36     config_.audio = true;
37     config_.ssrc = config.audio_ssrc;
38     config_.payload_type = config.audio_rtp_config.payload_type;
39     config_.frequency = config.audio_frequency;
40     config_.audio_codec = config.audio_codec;
41   } else {
42     storage_.reset(
43         new PacketStorage(clock, config.audio_rtp_config.history_ms));
44     config_.audio = false;
45     config_.ssrc = config.video_ssrc;
46     config_.payload_type = config.video_rtp_config.payload_type;
47     config_.frequency = kVideoFrequency;
48     config_.video_codec = config.video_codec;
49   }
50   // Randomly set start values.
51   config_.sequence_number = base::RandInt(0, 65535);
52   packetizer_.reset(
53       new RtpPacketizer(transport, storage_.get(), config_));
54 }
55
56 RtpSender::~RtpSender() {}
57
58 void RtpSender::IncomingEncodedVideoFrame(const EncodedVideoFrame* video_frame,
59                                           const base::TimeTicks& capture_time) {
60   packetizer_->IncomingEncodedVideoFrame(video_frame, capture_time);
61 }
62
63 void RtpSender::IncomingEncodedAudioFrame(
64     const EncodedAudioFrame* audio_frame,
65     const base::TimeTicks& recorded_time) {
66   packetizer_->IncomingEncodedAudioFrame(audio_frame, recorded_time);
67 }
68
69 void RtpSender::ResendPackets(
70     const MissingFramesAndPacketsMap& missing_frames_and_packets) {
71   // Iterate over all frames in the list.
72   for (MissingFramesAndPacketsMap::const_iterator it =
73            missing_frames_and_packets.begin();
74        it != missing_frames_and_packets.end();
75        ++it) {
76     PacketList packets_to_resend;
77     uint8 frame_id = it->first;
78     const PacketIdSet& packets_set = it->second;
79     bool success = false;
80
81     if (packets_set.empty()) {
82       VLOG(1) << "Missing all packets in frame " << static_cast<int>(frame_id);
83
84       uint16 packet_id = 0;
85       do {
86         // Get packet from storage.
87         success = storage_->GetPacket(frame_id, packet_id, &packets_to_resend);
88
89         // Resend packet to the network.
90         if (success) {
91           VLOG(1) << "Resend " << static_cast<int>(frame_id) << ":"
92                   << packet_id;
93           // Set a unique incremental sequence number for every packet.
94           Packet& packet = packets_to_resend.back();
95           UpdateSequenceNumber(&packet);
96           // Set the size as correspond to each frame.
97           ++packet_id;
98         }
99       } while (success);
100     } else {
101       // Iterate over all of the packets in the frame.
102       for (PacketIdSet::const_iterator set_it = packets_set.begin();
103            set_it != packets_set.end();
104            ++set_it) {
105         uint16 packet_id = *set_it;
106         success = storage_->GetPacket(frame_id, packet_id, &packets_to_resend);
107
108         // Resend packet to the network.
109         if (success) {
110           VLOG(1) << "Resend " << static_cast<int>(frame_id) << ":"
111                   << packet_id;
112           Packet& packet = packets_to_resend.back();
113           UpdateSequenceNumber(&packet);
114         }
115       }
116     }
117     transport_->ResendPackets(packets_to_resend);
118   }
119 }
120
121 void RtpSender::UpdateSequenceNumber(Packet* packet) {
122   uint16 new_sequence_number = packetizer_->NextSequenceNumber();
123   int index = 2;
124   (*packet)[index] = (static_cast<uint8>(new_sequence_number));
125   (*packet)[index + 1] = (static_cast<uint8>(new_sequence_number >> 8));
126 }
127
128 void RtpSender::SubscribeRtpStatsCallback(
129     const CastTransportRtpStatistics& callback) {
130   stats_callback_ = callback;
131   ScheduleNextStatsReport();
132 }
133
134 void RtpSender::ScheduleNextStatsReport() {
135   transport_task_runner_->PostDelayedTask(
136       FROM_HERE,
137       base::Bind(&RtpSender::RtpStatistics, base::AsWeakPtr(this)),
138       base::TimeDelta::FromMilliseconds(kStatsCallbackIntervalMs));
139 }
140
141 void RtpSender::RtpStatistics() {
142   RtcpSenderInfo sender_info;
143   base::TimeTicks time_sent;
144   uint32 rtp_timestamp = 0;
145   packetizer_->LastSentTimestamp(&time_sent, &rtp_timestamp);
146   sender_info.send_packet_count = packetizer_->send_packets_count();
147   sender_info.send_octet_count = packetizer_->send_octet_count();
148   stats_callback_.Run(sender_info, time_sent, rtp_timestamp);
149   ScheduleNextStatsReport();
150 }
151
152 }  // namespace transport
153 }  //  namespace cast
154 }  // namespace media