[SyncFS] Initialize SyncWorker when sync is enabled.
[chromium-blink-merge.git] / media / cast / sender / audio_sender.cc
blob9d33bce196eb6e0b4e56f7a805ebd89f3c379965
1 // Copyright 2014 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/sender/audio_sender.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "media/cast/cast_defines.h"
11 #include "media/cast/net/cast_transport_config.h"
12 #include "media/cast/sender/audio_encoder.h"
14 namespace media {
15 namespace cast {
16 namespace {
18 const int kNumAggressiveReportsSentAtStart = 100;
20 // TODO(miu): This should be specified in AudioSenderConfig, but currently it is
21 // fixed to 100 FPS (i.e., 10 ms per frame), and AudioEncoder assumes this as
22 // well.
23 const int kAudioFrameRate = 100;
25 } // namespace
27 AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment,
28 const AudioSenderConfig& audio_config,
29 CastTransportSender* const transport_sender)
30 : FrameSender(
31 cast_environment,
32 transport_sender,
33 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
34 audio_config.frequency,
35 audio_config.ssrc,
36 kAudioFrameRate * 2.0, // We lie to increase max outstanding frames.
37 audio_config.target_playout_delay),
38 configured_encoder_bitrate_(audio_config.bitrate),
39 weak_factory_(this) {
40 cast_initialization_status_ = STATUS_AUDIO_UNINITIALIZED;
41 VLOG(1) << "max_unacked_frames " << max_unacked_frames_;
42 DCHECK_GT(max_unacked_frames_, 0);
44 if (!audio_config.use_external_encoder) {
45 audio_encoder_.reset(
46 new AudioEncoder(cast_environment,
47 audio_config.channels,
48 audio_config.frequency,
49 audio_config.bitrate,
50 audio_config.codec,
51 base::Bind(&AudioSender::SendEncodedAudioFrame,
52 weak_factory_.GetWeakPtr())));
53 cast_initialization_status_ = audio_encoder_->InitializationResult();
54 } else {
55 NOTREACHED(); // No support for external audio encoding.
56 cast_initialization_status_ = STATUS_AUDIO_UNINITIALIZED;
59 media::cast::CastTransportRtpConfig transport_config;
60 transport_config.ssrc = audio_config.ssrc;
61 transport_config.feedback_ssrc = audio_config.incoming_feedback_ssrc;
62 transport_config.rtp_payload_type = audio_config.rtp_payload_type;
63 // TODO(miu): AudioSender needs to be like VideoSender in providing an upper
64 // limit on the number of in-flight frames.
65 transport_config.stored_frames = max_unacked_frames_;
66 transport_config.aes_key = audio_config.aes_key;
67 transport_config.aes_iv_mask = audio_config.aes_iv_mask;
69 transport_sender->InitializeAudio(
70 transport_config,
71 base::Bind(&AudioSender::OnReceivedCastFeedback,
72 weak_factory_.GetWeakPtr()),
73 base::Bind(&AudioSender::OnReceivedRtt, weak_factory_.GetWeakPtr()));
76 AudioSender::~AudioSender() {}
78 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus,
79 const base::TimeTicks& recorded_time) {
80 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
81 if (cast_initialization_status_ != STATUS_AUDIO_INITIALIZED) {
82 NOTREACHED();
83 return;
85 DCHECK(audio_encoder_.get()) << "Invalid internal state";
87 if (ShouldDropNextFrame(recorded_time)) {
88 VLOG(1) << "Dropping frame due to too many frames currently in-flight.";
89 return;
92 audio_encoder_->InsertAudio(audio_bus.Pass(), recorded_time);
95 void AudioSender::SendEncodedAudioFrame(
96 scoped_ptr<EncodedFrame> encoded_frame) {
97 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
99 const uint32 frame_id = encoded_frame->frame_id;
101 const bool is_first_frame_to_be_sent = last_send_time_.is_null();
102 last_send_time_ = cast_environment_->Clock()->NowTicks();
103 last_sent_frame_id_ = frame_id;
104 // If this is the first frame about to be sent, fake the value of
105 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up.
106 // Also, schedule the periodic frame re-send checks.
107 if (is_first_frame_to_be_sent) {
108 latest_acked_frame_id_ = frame_id - 1;
109 ScheduleNextResendCheck();
112 cast_environment_->Logging()->InsertEncodedFrameEvent(
113 last_send_time_, FRAME_ENCODED, AUDIO_EVENT, encoded_frame->rtp_timestamp,
114 frame_id, static_cast<int>(encoded_frame->data.size()),
115 encoded_frame->dependency == EncodedFrame::KEY,
116 configured_encoder_bitrate_);
118 RecordLatestFrameTimestamps(frame_id,
119 encoded_frame->reference_time,
120 encoded_frame->rtp_timestamp);
122 // At the start of the session, it's important to send reports before each
123 // frame so that the receiver can properly compute playout times. The reason
124 // more than one report is sent is because transmission is not guaranteed,
125 // only best effort, so we send enough that one should almost certainly get
126 // through.
127 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
128 // SendRtcpReport() will schedule future reports to be made if this is the
129 // last "aggressive report."
130 ++num_aggressive_rtcp_reports_sent_;
131 const bool is_last_aggressive_report =
132 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart);
133 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report.";
134 SendRtcpReport(is_last_aggressive_report);
137 if (send_target_playout_delay_) {
138 encoded_frame->new_playout_delay_ms =
139 target_playout_delay_.InMilliseconds();
141 transport_sender_->InsertCodedAudioFrame(*encoded_frame);
144 void AudioSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
145 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
147 if (is_rtt_available()) {
148 // Having the RTT values implies the receiver sent back a receiver report
149 // based on it having received a report from here. Therefore, ensure this
150 // sender stops aggressively sending reports.
151 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
152 VLOG(1) << "No longer a need to send reports aggressively (sent "
153 << num_aggressive_rtcp_reports_sent_ << ").";
154 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart;
155 ScheduleNextRtcpReport();
159 if (last_send_time_.is_null())
160 return; // Cannot get an ACK without having first sent a frame.
162 if (cast_feedback.missing_frames_and_packets.empty()) {
163 // We only count duplicate ACKs when we have sent newer frames.
164 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id &&
165 latest_acked_frame_id_ != last_sent_frame_id_) {
166 duplicate_ack_counter_++;
167 } else {
168 duplicate_ack_counter_ = 0;
170 // TODO(miu): The values "2" and "3" should be derived from configuration.
171 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) {
172 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_;
173 ResendForKickstart();
175 } else {
176 // Only count duplicated ACKs if there is no NACK request in between.
177 // This is to avoid aggresive resend.
178 duplicate_ack_counter_ = 0;
181 cast_environment_->Logging()->InsertFrameEvent(
182 cast_environment_->Clock()->NowTicks(),
183 FRAME_ACK_RECEIVED,
184 AUDIO_EVENT,
185 GetRecordedRtpTimestamp(cast_feedback.ack_frame_id),
186 cast_feedback.ack_frame_id);
188 const bool is_acked_out_of_order =
189 static_cast<int32>(cast_feedback.ack_frame_id -
190 latest_acked_frame_id_) < 0;
191 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "")
192 << " for frame " << cast_feedback.ack_frame_id;
193 if (!is_acked_out_of_order) {
194 // Cancel resends of acked frames.
195 std::vector<uint32> cancel_sending_frames;
196 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) {
197 latest_acked_frame_id_++;
198 cancel_sending_frames.push_back(latest_acked_frame_id_);
200 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames);
201 latest_acked_frame_id_ = cast_feedback.ack_frame_id;
205 bool AudioSender::ShouldDropNextFrame(base::TimeTicks capture_time) const {
206 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
207 int frames_in_flight = 0;
208 base::TimeDelta duration_in_flight;
209 if (!last_send_time_.is_null()) {
210 frames_in_flight =
211 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_);
212 if (frames_in_flight > 0) {
213 const uint32 oldest_unacked_frame_id = latest_acked_frame_id_ + 1;
214 duration_in_flight =
215 capture_time - GetRecordedReferenceTime(oldest_unacked_frame_id);
218 VLOG(2) << frames_in_flight
219 << " frames in flight; last sent: " << last_sent_frame_id_
220 << "; latest acked: " << latest_acked_frame_id_
221 << "; duration in flight: "
222 << duration_in_flight.InMicroseconds() << " usec ("
223 << (target_playout_delay_ > base::TimeDelta() ?
224 100 * duration_in_flight / target_playout_delay_ :
225 kint64max) << "%)";
226 return frames_in_flight >= max_unacked_frames_ ||
227 duration_in_flight >= target_playout_delay_;
230 } // namespace cast
231 } // namespace media