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

Side by Side Diff: media/cast/audio_receiver/audio_receiver.cc

Issue 280993002: [Cast] Repair receiver playout time calculations and frame skip logic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 7 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/audio_receiver/audio_receiver.h" 5 #include "media/cast/audio_receiver/audio_receiver.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 11 matching lines...) Expand all
22 namespace cast { 22 namespace cast {
23 23
24 AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment, 24 AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment,
25 const AudioReceiverConfig& audio_config, 25 const AudioReceiverConfig& audio_config,
26 transport::PacedPacketSender* const packet_sender) 26 transport::PacedPacketSender* const packet_sender)
27 : RtpReceiver(cast_environment->Clock(), &audio_config, NULL), 27 : RtpReceiver(cast_environment->Clock(), &audio_config, NULL),
28 cast_environment_(cast_environment), 28 cast_environment_(cast_environment),
29 event_subscriber_(kReceiverRtcpEventHistorySize, AUDIO_EVENT), 29 event_subscriber_(kReceiverRtcpEventHistorySize, AUDIO_EVENT),
30 codec_(audio_config.codec), 30 codec_(audio_config.codec),
31 frequency_(audio_config.frequency), 31 frequency_(audio_config.frequency),
32 target_delay_delta_( 32 target_playout_delay_(
33 base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms)), 33 base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms)),
34 reports_are_scheduled_(false),
34 framer_(cast_environment->Clock(), 35 framer_(cast_environment->Clock(),
35 this, 36 this,
36 audio_config.incoming_ssrc, 37 audio_config.incoming_ssrc,
37 true, 38 true,
38 audio_config.rtp_max_delay_ms / kTypicalAudioFrameDurationMs), 39 audio_config.rtp_max_delay_ms / kTypicalAudioFrameDurationMs),
39 rtcp_(cast_environment, 40 rtcp_(cast_environment,
40 NULL, 41 NULL,
41 NULL, 42 NULL,
42 packet_sender, 43 packet_sender,
43 GetStatistics(), 44 GetStatistics(),
44 audio_config.rtcp_mode, 45 audio_config.rtcp_mode,
45 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval), 46 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
46 audio_config.feedback_ssrc, 47 audio_config.feedback_ssrc,
47 audio_config.incoming_ssrc, 48 audio_config.incoming_ssrc,
48 audio_config.rtcp_c_name, 49 audio_config.rtcp_c_name,
49 true), 50 true),
50 is_waiting_for_consecutive_frame_(false), 51 is_waiting_for_consecutive_frame_(false),
52 lip_sync_drift_(ClockDriftSmoother::GetDefaultTimeConstant()),
51 weak_factory_(this) { 53 weak_factory_(this) {
52 if (!audio_config.use_external_decoder) 54 if (!audio_config.use_external_decoder)
53 audio_decoder_.reset(new AudioDecoder(cast_environment, audio_config)); 55 audio_decoder_.reset(new AudioDecoder(cast_environment, audio_config));
54 decryptor_.Initialize(audio_config.aes_key, audio_config.aes_iv_mask); 56 decryptor_.Initialize(audio_config.aes_key, audio_config.aes_iv_mask);
55 rtcp_.SetTargetDelay(target_delay_delta_); 57 rtcp_.SetTargetDelay(target_playout_delay_);
56 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_); 58 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_);
57 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); 59 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_));
58 } 60 }
59 61
60 AudioReceiver::~AudioReceiver() { 62 AudioReceiver::~AudioReceiver() {
61 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 63 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
62 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_); 64 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber_);
63 } 65 }
64 66
65 void AudioReceiver::InitializeTimers() {
66 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
67 ScheduleNextRtcpReport();
68 ScheduleNextCastMessage();
69 }
70
71 void AudioReceiver::OnReceivedPayloadData(const uint8* payload_data, 67 void AudioReceiver::OnReceivedPayloadData(const uint8* payload_data,
72 size_t payload_size, 68 size_t payload_size,
73 const RtpCastHeader& rtp_header) { 69 const RtpCastHeader& rtp_header) {
74 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 70 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
75 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
76 71
77 // TODO(pwestin): update this as video to refresh over time. 72 const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
78 if (time_first_incoming_packet_.is_null()) {
79 InitializeTimers();
80 first_incoming_rtp_timestamp_ = rtp_header.rtp_timestamp;
81 time_first_incoming_packet_ = now;
82 }
83 73
84 frame_id_to_rtp_timestamp_[rtp_header.frame_id & 0xff] = 74 frame_id_to_rtp_timestamp_[rtp_header.frame_id & 0xff] =
85 rtp_header.rtp_timestamp; 75 rtp_header.rtp_timestamp;
86 cast_environment_->Logging()->InsertPacketEvent( 76 cast_environment_->Logging()->InsertPacketEvent(
87 now, PACKET_RECEIVED, AUDIO_EVENT, rtp_header.rtp_timestamp, 77 now, PACKET_RECEIVED, AUDIO_EVENT, rtp_header.rtp_timestamp,
88 rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id, 78 rtp_header.frame_id, rtp_header.packet_id, rtp_header.max_packet_id,
89 payload_size); 79 payload_size);
90 80
91 bool duplicate = false; 81 bool duplicate = false;
92 const bool complete = 82 const bool complete =
93 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); 83 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate);
94 84
95 // Duplicate packets are ignored. 85 // Duplicate packets are ignored.
96 if (duplicate || !complete) 86 if (duplicate)
87 return;
88
89 // Update lip-sync values upon receiving the first packet of each frame, or if
90 // they have never been set yet.
91 if (rtp_header.packet_id == 0 || lip_sync_reference_time_.is_null()) {
92 RtpTimestamp fresh_sync_rtp;
93 base::TimeTicks fresh_sync_reference;
94 if (!rtcp_.GetLatestLipSyncTimes(&fresh_sync_rtp, &fresh_sync_reference)) {
95 // HACK: The sender should have provided Sender Reports before the first
96 // frame was sent. However, the spec does not currently require this.
97 // Therefore, when the data is missing, the local clock is used to
98 // generate reference timestamps.
99 VLOG(2) << "Lip sync info missing. Falling-back to local clock.";
100 fresh_sync_rtp = rtp_header.rtp_timestamp;
101 fresh_sync_reference = now;
102 }
103 // |lip_sync_reference_time_| is always incremented according to the time
104 // delta computed from the difference in RTP timestamps. Then,
105 // |lip_sync_drift_| accounts for clock drift and also smoothes-out any
106 // sudden/discontinuous shifts in the series of reference time values.
107 if (lip_sync_reference_time_.is_null()) {
108 lip_sync_reference_time_ = fresh_sync_reference;
109 } else {
110 lip_sync_reference_time_ += RtpDeltaToTimeDelta(
111 static_cast<int32>(fresh_sync_rtp - lip_sync_rtp_timestamp_),
112 frequency_);
113 }
114 lip_sync_rtp_timestamp_ = fresh_sync_rtp;
115 lip_sync_drift_.Update(
116 now, fresh_sync_reference - lip_sync_reference_time_);
117 }
118
119 // Frame not complete; wait for more packets.
120 if (!complete)
97 return; 121 return;
98 122
99 EmitAvailableEncodedFrames(); 123 EmitAvailableEncodedFrames();
100 } 124 }
101 125
102 void AudioReceiver::GetRawAudioFrame( 126 void AudioReceiver::GetRawAudioFrame(
103 const AudioFrameDecodedCallback& callback) { 127 const AudioFrameDecodedCallback& callback) {
104 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 128 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
105 DCHECK(!callback.is_null()); 129 DCHECK(!callback.is_null());
106 DCHECK(audio_decoder_.get()); 130 DCHECK(audio_decoder_.get());
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 bool have_multiple_complete_frames = false; 196 bool have_multiple_complete_frames = false;
173 if (!framer_.GetEncodedFrame(encoded_frame.get(), 197 if (!framer_.GetEncodedFrame(encoded_frame.get(),
174 &is_consecutively_next_frame, 198 &is_consecutively_next_frame,
175 &have_multiple_complete_frames)) { 199 &have_multiple_complete_frames)) {
176 VLOG(1) << "Wait for more audio packets to produce a completed frame."; 200 VLOG(1) << "Wait for more audio packets to produce a completed frame.";
177 return; // OnReceivedPayloadData() will invoke this method in the future. 201 return; // OnReceivedPayloadData() will invoke this method in the future.
178 } 202 }
179 203
180 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 204 const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
181 const base::TimeTicks playout_time = 205 const base::TimeTicks playout_time =
182 GetPlayoutTime(now, encoded_frame->rtp_timestamp); 206 GetPlayoutTime(encoded_frame->rtp_timestamp);
183 207
184 // If we have multiple decodable frames, and the current frame is 208 // If we have multiple decodable frames, and the current frame is
185 // too old, then skip it and decode the next frame instead. 209 // too old, then skip it and decode the next frame instead.
186 if (have_multiple_complete_frames && now > playout_time) { 210 if (have_multiple_complete_frames && now > playout_time) {
187 framer_.ReleaseFrame(encoded_frame->frame_id); 211 framer_.ReleaseFrame(encoded_frame->frame_id);
188 continue; 212 continue;
189 } 213 }
190 214
191 // If |framer_| has a frame ready that is out of sequence, examine the 215 // If |framer_| has a frame ready that is out of sequence, examine the
192 // playout time to determine whether it's acceptable to continue, thereby 216 // playout time to determine whether it's acceptable to continue, thereby
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 } 260 }
237 } 261 }
238 262
239 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() { 263 void AudioReceiver::EmitAvailableEncodedFramesAfterWaiting() {
240 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 264 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
241 DCHECK(is_waiting_for_consecutive_frame_); 265 DCHECK(is_waiting_for_consecutive_frame_);
242 is_waiting_for_consecutive_frame_ = false; 266 is_waiting_for_consecutive_frame_ = false;
243 EmitAvailableEncodedFrames(); 267 EmitAvailableEncodedFrames();
244 } 268 }
245 269
270 base::TimeTicks AudioReceiver::GetPlayoutTime(uint32 rtp_timestamp) const {
271 return lip_sync_reference_time_ +
272 lip_sync_drift_.Current() +
273 RtpDeltaToTimeDelta(
274 static_cast<int32>(rtp_timestamp - lip_sync_rtp_timestamp_),
275 frequency_) +
276 target_playout_delay_;
277 }
278
246 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) { 279 void AudioReceiver::IncomingPacket(scoped_ptr<Packet> packet) {
247 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 280 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
248 if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) { 281 if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) {
249 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); 282 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size());
250 } else { 283 } else {
251 ReceivedPacket(&packet->front(), packet->size()); 284 ReceivedPacket(&packet->front(), packet->size());
252 } 285 }
253 } 286 if (!reports_are_scheduled_) {
254 287 ScheduleNextRtcpReport();
255 void AudioReceiver::SetTargetDelay(base::TimeDelta target_delay) { 288 ScheduleNextCastMessage();
256 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 289 reports_are_scheduled_ = true;
257 target_delay_delta_ = target_delay; 290 }
258 rtcp_.SetTargetDelay(target_delay_delta_);
259 } 291 }
260 292
261 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { 293 void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) {
262 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 294 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
263 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 295 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
264 RtpTimestamp rtp_timestamp = 296 RtpTimestamp rtp_timestamp =
265 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id_ & 0xff]; 297 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id_ & 0xff];
266 cast_environment_->Logging()->InsertFrameEvent( 298 cast_environment_->Logging()->InsertFrameEvent(
267 now, FRAME_ACK_SENT, AUDIO_EVENT, rtp_timestamp, 299 now, FRAME_ACK_SENT, AUDIO_EVENT, rtp_timestamp,
268 cast_message.ack_frame_id_); 300 cast_message.ack_frame_id_);
269 301
270 ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events; 302 ReceiverRtcpEventSubscriber::RtcpEventMultiMap rtcp_events;
271 event_subscriber_.GetRtcpEventsAndReset(&rtcp_events); 303 event_subscriber_.GetRtcpEventsAndReset(&rtcp_events);
272 rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events); 304 rtcp_.SendRtcpFromRtpReceiver(&cast_message, &rtcp_events);
273 } 305 }
274 306
275 base::TimeTicks AudioReceiver::GetPlayoutTime(base::TimeTicks now,
276 uint32 rtp_timestamp) {
277 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
278 // Senders time in ms when this frame was recorded.
279 // Note: the senders clock and our local clock might not be synced.
280 base::TimeTicks rtp_timestamp_in_ticks;
281 base::TimeTicks playout_time;
282 if (time_offset_ == base::TimeDelta()) {
283 if (rtcp_.RtpTimestampInSenderTime(frequency_,
284 first_incoming_rtp_timestamp_,
285 &rtp_timestamp_in_ticks)) {
286 time_offset_ = time_first_incoming_packet_ - rtp_timestamp_in_ticks;
287 // TODO(miu): As clocks drift w.r.t. each other, and other factors take
288 // effect, |time_offset_| should be updated. Otherwise, we might as well
289 // always compute the time offsets agnostic of RTCP's time data.
290 } else {
291 // We have not received any RTCP to sync the stream play it out as soon as
292 // possible.
293
294 // BUG: This means we're literally switching to a different timeline a
295 // short time after a cast receiver has been running. Re-enable
296 // End2EndTest.StartSenderBeforeReceiver once this is fixed.
297 // http://crbug.com/356942
298 uint32 rtp_timestamp_diff = rtp_timestamp - first_incoming_rtp_timestamp_;
299
300 int frequency_khz = frequency_ / 1000;
301 base::TimeDelta rtp_time_diff_delta =
302 base::TimeDelta::FromMilliseconds(rtp_timestamp_diff / frequency_khz);
303 base::TimeDelta time_diff_delta = now - time_first_incoming_packet_;
304
305 playout_time = now + std::max(rtp_time_diff_delta - time_diff_delta,
306 base::TimeDelta());
307 }
308 }
309 if (playout_time.is_null()) {
310 // This can fail if we have not received any RTCP packets in a long time.
311 if (rtcp_.RtpTimestampInSenderTime(frequency_, rtp_timestamp,
312 &rtp_timestamp_in_ticks)) {
313 playout_time =
314 rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_;
315 } else {
316 playout_time = now;
317 }
318 }
319
320 // TODO(miu): This is broken since we literally switch timelines once |rtcp_|
321 // can provide us the |time_offset_|. Furthermore, this "getter" method may
322 // be called on frames received out-of-order, which means the playout times
323 // for earlier frames will be computed incorrectly.
324 #if 0
325 // Don't allow the playout time to go backwards.
326 if (last_playout_time_ > playout_time) playout_time = last_playout_time_;
327 last_playout_time_ = playout_time;
328 #endif
329
330 return playout_time;
331 }
332
333 void AudioReceiver::ScheduleNextRtcpReport() { 307 void AudioReceiver::ScheduleNextRtcpReport() {
334 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 308 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
335 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() - 309 base::TimeDelta time_to_send = rtcp_.TimeToSendNextRtcpReport() -
336 cast_environment_->Clock()->NowTicks(); 310 cast_environment_->Clock()->NowTicks();
337 311
338 time_to_send = std::max( 312 time_to_send = std::max(
339 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 313 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
340 314
341 cast_environment_->PostDelayedTask( 315 cast_environment_->PostDelayedTask(
342 CastEnvironment::MAIN, 316 CastEnvironment::MAIN,
(...skipping 29 matching lines...) Expand all
372 } 346 }
373 347
374 void AudioReceiver::SendNextCastMessage() { 348 void AudioReceiver::SendNextCastMessage() {
375 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 349 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
376 framer_.SendCastMessage(); // Will only send a message if it is time. 350 framer_.SendCastMessage(); // Will only send a message if it is time.
377 ScheduleNextCastMessage(); 351 ScheduleNextCastMessage();
378 } 352 }
379 353
380 } // namespace cast 354 } // namespace cast
381 } // namespace media 355 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/audio_receiver/audio_receiver.h ('k') | media/cast/audio_receiver/audio_receiver_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698