Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / media / cast / audio_sender / audio_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/audio_sender/audio_sender.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "media/cast/audio_sender/audio_encoder.h"
11 #include "media/cast/transport/cast_transport_defines.h"
12
13 namespace media {
14 namespace cast {
15
16 const int64 kMinSchedulingDelayMs = 1;
17
18 class LocalRtcpAudioSenderFeedback : public RtcpSenderFeedback {
19  public:
20   explicit LocalRtcpAudioSenderFeedback(AudioSender* audio_sender)
21       : audio_sender_(audio_sender) {}
22
23   virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback)
24       OVERRIDE {
25     if (!cast_feedback.missing_frames_and_packets_.empty()) {
26       audio_sender_->ResendPackets(cast_feedback.missing_frames_and_packets_);
27     }
28     VLOG(1) << "Received audio ACK "
29             << static_cast<int>(cast_feedback.ack_frame_id_);
30   }
31
32  private:
33   AudioSender* audio_sender_;
34
35   DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtcpAudioSenderFeedback);
36 };
37
38 class LocalRtpSenderStatistics : public RtpSenderStatistics {
39  public:
40   LocalRtpSenderStatistics(
41       transport::CastTransportSender* const transport_sender,
42       int frequency)
43       : transport_sender_(transport_sender),
44         frequency_(0),
45         sender_info_(),
46         rtp_timestamp_(0) {
47     transport_sender_->SubscribeAudioRtpStatsCallback(base::Bind(
48         &LocalRtpSenderStatistics::StoreStatistics, base::Unretained(this)));
49   }
50
51   virtual void GetStatistics(const base::TimeTicks& now,
52                              transport::RtcpSenderInfo* sender_info) OVERRIDE {
53     // Update and return last stored statistics.
54     uint32 ntp_seconds = 0;
55     uint32 ntp_fraction = 0;
56     uint32 rtp_timestamp = 0;
57     if (rtp_timestamp_ > 0) {
58       base::TimeDelta time_since_last_send = now - time_sent_;
59       rtp_timestamp = rtp_timestamp_ + time_since_last_send.InMilliseconds() *
60                                            (frequency_ / 1000);
61       // Update NTP time to current time.
62       ConvertTimeTicksToNtp(now, &ntp_seconds, &ntp_fraction);
63     }
64     // Populate sender info.
65     sender_info->rtp_timestamp = rtp_timestamp;
66     sender_info->ntp_seconds = sender_info_.ntp_seconds;
67     sender_info->ntp_fraction = sender_info_.ntp_fraction;
68     sender_info->send_packet_count = sender_info_.send_packet_count;
69     sender_info->send_octet_count = sender_info_.send_octet_count;
70   }
71
72   void StoreStatistics(const transport::RtcpSenderInfo& sender_info,
73                        base::TimeTicks time_sent,
74                        uint32 rtp_timestamp) {
75     sender_info_ = sender_info;
76     time_sent_ = time_sent;
77     rtp_timestamp_ = rtp_timestamp;
78   }
79
80  private:
81   transport::CastTransportSender* const transport_sender_;
82   int frequency_;
83   transport::RtcpSenderInfo sender_info_;
84   base::TimeTicks time_sent_;
85   uint32 rtp_timestamp_;
86
87   DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtpSenderStatistics);
88 };
89
90 // TODO(mikhal): Reduce heap allocation when not needed.
91 AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment,
92                          const AudioSenderConfig& audio_config,
93                          transport::CastTransportSender* const transport_sender)
94     : cast_environment_(cast_environment),
95       transport_sender_(transport_sender),
96       rtcp_feedback_(new LocalRtcpAudioSenderFeedback(this)),
97       rtp_audio_sender_statistics_(
98           new LocalRtpSenderStatistics(transport_sender_,
99                                        audio_config.frequency)),
100       rtcp_(cast_environment,
101             rtcp_feedback_.get(),
102             transport_sender_,
103             NULL,  // paced sender.
104             rtp_audio_sender_statistics_.get(),
105             NULL,
106             audio_config.rtcp_mode,
107             base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
108             audio_config.sender_ssrc,
109             audio_config.incoming_feedback_ssrc,
110             audio_config.rtcp_c_name),
111       timers_initialized_(false),
112       initialization_status_(STATUS_INITIALIZED),
113       weak_factory_(this) {
114   if (!audio_config.use_external_encoder) {
115     audio_encoder_ =
116         new AudioEncoder(cast_environment,
117                          audio_config,
118                          base::Bind(&AudioSender::SendEncodedAudioFrame,
119                                     weak_factory_.GetWeakPtr()));
120     initialization_status_ = audio_encoder_->InitializationResult();
121   }
122 }
123
124 AudioSender::~AudioSender() {}
125
126 void AudioSender::InitializeTimers() {
127   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
128   if (!timers_initialized_) {
129     timers_initialized_ = true;
130     ScheduleNextRtcpReport();
131   }
132 }
133
134 void AudioSender::InsertAudio(const AudioBus* audio_bus,
135                               const base::TimeTicks& recorded_time,
136                               const base::Closure& done_callback) {
137   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
138   DCHECK(audio_encoder_.get()) << "Invalid internal state";
139
140   audio_encoder_->InsertAudio(audio_bus, recorded_time, done_callback);
141 }
142
143 void AudioSender::SendEncodedAudioFrame(
144     scoped_ptr<transport::EncodedAudioFrame> audio_frame,
145     const base::TimeTicks& recorded_time) {
146   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
147   InitializeTimers();
148   cast_environment_->PostTask(
149       CastEnvironment::TRANSPORT,
150       FROM_HERE,
151       base::Bind(&AudioSender::SendEncodedAudioFrameToTransport,
152                  base::Unretained(this),
153                  base::Passed(&audio_frame),
154                  recorded_time));
155 }
156
157 void AudioSender::SendEncodedAudioFrameToTransport(
158     scoped_ptr<transport::EncodedAudioFrame> audio_frame,
159     const base::TimeTicks& recorded_time) {
160   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
161   transport_sender_->InsertCodedAudioFrame(audio_frame.get(), recorded_time);
162 }
163
164 void AudioSender::ResendPackets(
165     const MissingFramesAndPacketsMap& missing_frames_and_packets) {
166   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
167   cast_environment_->PostTask(
168       CastEnvironment::TRANSPORT,
169       FROM_HERE,
170       base::Bind(&AudioSender::ResendPacketsOnTransportThread,
171                  base::Unretained(this),
172                  missing_frames_and_packets));
173 }
174
175 void AudioSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) {
176   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
177   rtcp_.IncomingRtcpPacket(&packet->front(), packet->size());
178 }
179
180 void AudioSender::ScheduleNextRtcpReport() {
181   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
182   base::TimeDelta time_to_next =
183       rtcp_.TimeToSendNextRtcpReport() - cast_environment_->Clock()->NowTicks();
184
185   time_to_next = std::max(
186       time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
187
188   cast_environment_->PostDelayedTask(
189       CastEnvironment::MAIN,
190       FROM_HERE,
191       base::Bind(&AudioSender::SendRtcpReport, weak_factory_.GetWeakPtr()),
192       time_to_next);
193 }
194
195 void AudioSender::SendRtcpReport() {
196   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
197   // We don't send audio logging messages since all captured audio frames will
198   // be sent.
199   transport::RtcpSenderLogMessage empty_msg;
200   rtcp_.SendRtcpFromRtpSender(empty_msg);
201   ScheduleNextRtcpReport();
202 }
203
204 void AudioSender::ResendPacketsOnTransportThread(
205     const transport::MissingFramesAndPacketsMap& missing_packets) {
206   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
207   transport_sender_->ResendPackets(true, missing_packets);
208 }
209
210 }  // namespace cast
211 }  // namespace media