Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: media/cast/sender/audio_sender.cc

Issue 387933005: Cast: Refactor RTCP handling (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: smaller diff Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/cast/sender/audio_sender.h" 5 #include "media/cast/sender/audio_sender.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "media/cast/cast_defines.h" 10 #include "media/cast/cast_defines.h"
11 #include "media/cast/net/cast_transport_config.h" 11 #include "media/cast/net/cast_transport_config.h"
12 #include "media/cast/net/rtcp/rtcp_defines.h" 12 #include "media/cast/net/rtcp/rtcp_defines.h"
miu 2014/07/16 19:58:03 Remove this include.
Alpha Left Google 2014/07/17 01:01:46 Done.
13 #include "media/cast/sender/audio_encoder.h" 13 #include "media/cast/sender/audio_encoder.h"
14 14
15 namespace media { 15 namespace media {
16 namespace cast { 16 namespace cast {
17 namespace { 17 namespace {
18 18
19 const int kNumAggressiveReportsSentAtStart = 100; 19 const int kNumAggressiveReportsSentAtStart = 100;
20 const int kMinSchedulingDelayMs = 1; 20 const int kMinSchedulingDelayMs = 1;
21 21
22 // TODO(miu): This should be specified in AudioSenderConfig, but currently it is 22 // TODO(miu): This should be specified in AudioSenderConfig, but currently it is
23 // fixed to 100 FPS (i.e., 10 ms per frame), and AudioEncoder assumes this as 23 // fixed to 100 FPS (i.e., 10 ms per frame), and AudioEncoder assumes this as
24 // well. 24 // well.
25 const int kAudioFrameRate = 100; 25 const int kAudioFrameRate = 100;
26 26
27 // Helper function to compute the maximum unacked audio frames that is sent. 27 // Helper function to compute the maximum unacked audio frames that is sent.
28 int GetMaxUnackedFrames(base::TimeDelta target_delay) { 28 int GetMaxUnackedFrames(base::TimeDelta target_delay) {
29 // As long as it doesn't go over |kMaxUnackedFrames|, it is okay to send more 29 // As long as it doesn't go over |kMaxUnackedFrames|, it is okay to send more
30 // audio data than the target delay would suggest. Audio packets are tiny and 30 // audio data than the target delay would suggest. Audio packets are tiny and
31 // receiver has the ability to drop any one of the packets. 31 // receiver has the ability to drop any one of the packets.
32 // We send up to three times of the target delay of audio frames. 32 // We send up to three times of the target delay of audio frames.
33 int frames = 33 int frames =
34 1 + 3 * target_delay * kAudioFrameRate / base::TimeDelta::FromSeconds(1); 34 1 + 3 * target_delay * kAudioFrameRate / base::TimeDelta::FromSeconds(1);
35 return std::min(kMaxUnackedFrames, frames); 35 return std::min(kMaxUnackedFrames, frames);
36 } 36 }
37 } // namespace 37 } // namespace
38 38
39 AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment, 39 AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment,
40 const AudioSenderConfig& audio_config, 40 const AudioSenderConfig& audio_config,
41 CastTransportSender* const transport_sender) 41 CastTransportSender* const transport_sender)
42 : cast_environment_(cast_environment), 42 : FrameSender(
43 cast_environment,
44 transport_sender,
45 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
46 audio_config.frequency,
47 true),
43 target_playout_delay_(audio_config.target_playout_delay), 48 target_playout_delay_(audio_config.target_playout_delay),
44 transport_sender_(transport_sender),
45 max_unacked_frames_(GetMaxUnackedFrames(target_playout_delay_)), 49 max_unacked_frames_(GetMaxUnackedFrames(target_playout_delay_)),
46 configured_encoder_bitrate_(audio_config.bitrate), 50 configured_encoder_bitrate_(audio_config.bitrate),
47 rtcp_(cast_environment,
48 this,
49 transport_sender_,
50 NULL, // paced sender.
51 NULL,
52 audio_config.rtcp_mode,
53 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
54 audio_config.ssrc,
55 audio_config.incoming_feedback_ssrc,
56 audio_config.rtcp_c_name,
57 AUDIO_EVENT),
58 rtp_timestamp_helper_(audio_config.frequency),
59 num_aggressive_rtcp_reports_sent_(0), 51 num_aggressive_rtcp_reports_sent_(0),
60 last_sent_frame_id_(0), 52 last_sent_frame_id_(0),
61 latest_acked_frame_id_(0), 53 latest_acked_frame_id_(0),
62 duplicate_ack_counter_(0), 54 duplicate_ack_counter_(0),
63 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), 55 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED),
64 weak_factory_(this) { 56 weak_factory_(this) {
65 VLOG(1) << "max_unacked_frames " << max_unacked_frames_; 57 VLOG(1) << "max_unacked_frames " << max_unacked_frames_;
66 DCHECK_GT(max_unacked_frames_, 0); 58 DCHECK_GT(max_unacked_frames_, 0);
67 59
68 if (!audio_config.use_external_encoder) { 60 if (!audio_config.use_external_encoder) {
69 audio_encoder_.reset( 61 audio_encoder_.reset(
70 new AudioEncoder(cast_environment, 62 new AudioEncoder(cast_environment,
71 audio_config.channels, 63 audio_config.channels,
72 audio_config.frequency, 64 audio_config.frequency,
73 audio_config.bitrate, 65 audio_config.bitrate,
74 audio_config.codec, 66 audio_config.codec,
75 base::Bind(&AudioSender::SendEncodedAudioFrame, 67 base::Bind(&AudioSender::SendEncodedAudioFrame,
76 weak_factory_.GetWeakPtr()))); 68 weak_factory_.GetWeakPtr())));
77 cast_initialization_status_ = audio_encoder_->InitializationResult(); 69 cast_initialization_status_ = audio_encoder_->InitializationResult();
78 } else { 70 } else {
79 NOTREACHED(); // No support for external audio encoding. 71 NOTREACHED(); // No support for external audio encoding.
80 cast_initialization_status_ = STATUS_AUDIO_UNINITIALIZED; 72 cast_initialization_status_ = STATUS_AUDIO_UNINITIALIZED;
81 } 73 }
82 74
83 media::cast::CastTransportRtpConfig transport_config; 75 media::cast::CastTransportRtpConfig transport_config;
84 transport_config.ssrc = audio_config.ssrc; 76 transport_config.ssrc = audio_config.ssrc;
77 transport_config.feedback_ssrc = audio_config.incoming_feedback_ssrc;
78 transport_config.c_name = audio_config.rtcp_c_name;
85 transport_config.rtp_payload_type = audio_config.rtp_payload_type; 79 transport_config.rtp_payload_type = audio_config.rtp_payload_type;
86 // TODO(miu): AudioSender needs to be like VideoSender in providing an upper 80 // TODO(miu): AudioSender needs to be like VideoSender in providing an upper
87 // limit on the number of in-flight frames. 81 // limit on the number of in-flight frames.
88 transport_config.stored_frames = max_unacked_frames_; 82 transport_config.stored_frames = max_unacked_frames_;
89 transport_config.aes_key = audio_config.aes_key; 83 transport_config.aes_key = audio_config.aes_key;
90 transport_config.aes_iv_mask = audio_config.aes_iv_mask; 84 transport_config.aes_iv_mask = audio_config.aes_iv_mask;
91 transport_sender_->InitializeAudio(transport_config);
92 85
93 rtcp_.SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize); 86 transport_sender->InitializeAudio(
94 87 transport_config,
88 base::Bind(&AudioSender::OnReceivedCastFeedback,
89 weak_factory_.GetWeakPtr()),
90 base::Bind(&AudioSender::OnReceivedRtt, weak_factory_.GetWeakPtr()));
95 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); 91 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_));
96 } 92 }
97 93
98 AudioSender::~AudioSender() {} 94 AudioSender::~AudioSender() {}
99 95
100 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus, 96 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus,
101 const base::TimeTicks& recorded_time) { 97 const base::TimeTicks& recorded_time) {
102 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 98 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
103 if (cast_initialization_status_ != STATUS_AUDIO_INITIALIZED) { 99 if (cast_initialization_status_ != STATUS_AUDIO_INITIALIZED) {
104 NOTREACHED(); 100 NOTREACHED();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 ++num_aggressive_rtcp_reports_sent_; 150 ++num_aggressive_rtcp_reports_sent_;
155 const bool is_last_aggressive_report = 151 const bool is_last_aggressive_report =
156 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); 152 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart);
157 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report."; 153 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report.";
158 SendRtcpReport(is_last_aggressive_report); 154 SendRtcpReport(is_last_aggressive_report);
159 } 155 }
160 156
161 transport_sender_->InsertCodedAudioFrame(*encoded_frame); 157 transport_sender_->InsertCodedAudioFrame(*encoded_frame);
162 } 158 }
163 159
164 void AudioSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) {
165 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
166 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size());
167 }
168
169 void AudioSender::ScheduleNextRtcpReport() {
170 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
171 base::TimeDelta time_to_next =
172 rtcp_.TimeToSendNextRtcpReport() - cast_environment_->Clock()->NowTicks();
173
174 time_to_next = std::max(
175 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
176
177 cast_environment_->PostDelayedTask(
178 CastEnvironment::MAIN,
179 FROM_HERE,
180 base::Bind(&AudioSender::SendRtcpReport,
181 weak_factory_.GetWeakPtr(),
182 true),
183 time_to_next);
184 }
185
186 void AudioSender::SendRtcpReport(bool schedule_future_reports) {
187 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
188 const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
189 uint32 now_as_rtp_timestamp = 0;
190 if (rtp_timestamp_helper_.GetCurrentTimeAsRtpTimestamp(
191 now, &now_as_rtp_timestamp)) {
192 rtcp_.SendRtcpFromRtpSender(now, now_as_rtp_timestamp);
193 } else {
194 // |rtp_timestamp_helper_| should have stored a mapping by this point.
195 NOTREACHED();
196 }
197 if (schedule_future_reports)
198 ScheduleNextRtcpReport();
199 }
200
201 void AudioSender::ScheduleNextResendCheck() { 160 void AudioSender::ScheduleNextResendCheck() {
202 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 161 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
203 DCHECK(!last_send_time_.is_null()); 162 DCHECK(!last_send_time_.is_null());
204 base::TimeDelta time_to_next = 163 base::TimeDelta time_to_next =
205 last_send_time_ - cast_environment_->Clock()->NowTicks() + 164 last_send_time_ - cast_environment_->Clock()->NowTicks() +
206 target_playout_delay_; 165 target_playout_delay_;
207 time_to_next = std::max( 166 time_to_next = std::max(
208 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 167 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
209 cast_environment_->PostDelayedTask( 168 cast_environment_->PostDelayedTask(
210 CastEnvironment::MAIN, 169 CastEnvironment::MAIN,
(...skipping 14 matching lines...) Expand all
225 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; 184 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_;
226 ResendForKickstart(); 185 ResendForKickstart();
227 } 186 }
228 } 187 }
229 ScheduleNextResendCheck(); 188 ScheduleNextResendCheck();
230 } 189 }
231 190
232 void AudioSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { 191 void AudioSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
233 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 192 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
234 193
235 if (rtcp_.is_rtt_available()) { 194 if (is_rtt_available()) {
236 // Having the RTT values implies the receiver sent back a receiver report 195 // Having the RTT values implies the receiver sent back a receiver report
237 // based on it having received a report from here. Therefore, ensure this 196 // based on it having received a report from here. Therefore, ensure this
238 // sender stops aggressively sending reports. 197 // sender stops aggressively sending reports.
239 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { 198 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
240 VLOG(1) << "No longer a need to send reports aggressively (sent " 199 VLOG(1) << "No longer a need to send reports aggressively (sent "
241 << num_aggressive_rtcp_reports_sent_ << ")."; 200 << num_aggressive_rtcp_reports_sent_ << ").";
242 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart; 201 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart;
243 ScheduleNextRtcpReport(); 202 ScheduleNextRtcpReport();
244 } 203 }
245 } 204 }
(...skipping 12 matching lines...) Expand all
258 // TODO(miu): The values "2" and "3" should be derived from configuration. 217 // TODO(miu): The values "2" and "3" should be derived from configuration.
259 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { 218 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) {
260 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; 219 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_;
261 ResendForKickstart(); 220 ResendForKickstart();
262 } 221 }
263 } else { 222 } else {
264 // Only count duplicated ACKs if there is no NACK request in between. 223 // Only count duplicated ACKs if there is no NACK request in between.
265 // This is to avoid aggresive resend. 224 // This is to avoid aggresive resend.
266 duplicate_ack_counter_ = 0; 225 duplicate_ack_counter_ = 0;
267 226
268 base::TimeDelta rtt;
269 base::TimeDelta avg_rtt;
270 base::TimeDelta min_rtt;
271 base::TimeDelta max_rtt;
272 rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt);
273
274 // A NACK is also used to cancel pending re-transmissions. 227 // A NACK is also used to cancel pending re-transmissions.
275 transport_sender_->ResendPackets( 228 transport_sender_->ResendPackets(
276 true, cast_feedback.missing_frames_and_packets_, false, min_rtt); 229 true, cast_feedback.missing_frames_and_packets_, false, min_rtt_);
277 } 230 }
278 231
279 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 232 const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
280 233
281 const RtpTimestamp rtp_timestamp = 234 const RtpTimestamp rtp_timestamp =
282 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff]; 235 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff];
283 cast_environment_->Logging()->InsertFrameEvent(now, 236 cast_environment_->Logging()->InsertFrameEvent(now,
284 FRAME_ACK_RECEIVED, 237 FRAME_ACK_RECEIVED,
285 AUDIO_EVENT, 238 AUDIO_EVENT,
286 rtp_timestamp, 239 rtp_timestamp,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 // Send the first packet of the last encoded frame to kick start 279 // Send the first packet of the last encoded frame to kick start
327 // retransmission. This gives enough information to the receiver what 280 // retransmission. This gives enough information to the receiver what
328 // packets and frames are missing. 281 // packets and frames are missing.
329 MissingFramesAndPacketsMap missing_frames_and_packets; 282 MissingFramesAndPacketsMap missing_frames_and_packets;
330 PacketIdSet missing; 283 PacketIdSet missing;
331 missing.insert(kRtcpCastLastPacket); 284 missing.insert(kRtcpCastLastPacket);
332 missing_frames_and_packets.insert( 285 missing_frames_and_packets.insert(
333 std::make_pair(last_sent_frame_id_, missing)); 286 std::make_pair(last_sent_frame_id_, missing));
334 last_send_time_ = cast_environment_->Clock()->NowTicks(); 287 last_send_time_ = cast_environment_->Clock()->NowTicks();
335 288
336 base::TimeDelta rtt;
337 base::TimeDelta avg_rtt;
338 base::TimeDelta min_rtt;
339 base::TimeDelta max_rtt;
340 rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt);
341
342 // Sending this extra packet is to kick-start the session. There is 289 // Sending this extra packet is to kick-start the session. There is
343 // no need to optimize re-transmission for this case. 290 // no need to optimize re-transmission for this case.
344 transport_sender_->ResendPackets( 291 transport_sender_->ResendPackets(
345 true, missing_frames_and_packets, false, min_rtt); 292 true, missing_frames_and_packets, false, min_rtt_);
346 } 293 }
347 294
348 } // namespace cast 295 } // namespace cast
349 } // namespace media 296 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698