| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/receiver/frame_receiver.h" | 5 #include "media/cast/receiver/frame_receiver.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/big_endian.h" | 9 #include "base/big_endian.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 config.receiver_ssrc, | 52 config.receiver_ssrc, |
| 53 config.sender_ssrc), | 53 config.sender_ssrc), |
| 54 is_waiting_for_consecutive_frame_(false), | 54 is_waiting_for_consecutive_frame_(false), |
| 55 lip_sync_drift_(ClockDriftSmoother::GetDefaultTimeConstant()), | 55 lip_sync_drift_(ClockDriftSmoother::GetDefaultTimeConstant()), |
| 56 weak_factory_(this) { | 56 weak_factory_(this) { |
| 57 transport_->AddValidSsrc(config.sender_ssrc); | 57 transport_->AddValidSsrc(config.sender_ssrc); |
| 58 DCHECK_GT(config.rtp_max_delay_ms, 0); | 58 DCHECK_GT(config.rtp_max_delay_ms, 0); |
| 59 DCHECK_GT(config.target_frame_rate, 0); | 59 DCHECK_GT(config.target_frame_rate, 0); |
| 60 decryptor_.Initialize(config.aes_key, config.aes_iv_mask); | 60 decryptor_.Initialize(config.aes_key, config.aes_iv_mask); |
| 61 cast_environment_->logger()->Subscribe(&event_subscriber_); | 61 cast_environment_->logger()->Subscribe(&event_subscriber_); |
| 62 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); | |
| 63 } | 62 } |
| 64 | 63 |
| 65 FrameReceiver::~FrameReceiver() { | 64 FrameReceiver::~FrameReceiver() { |
| 66 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 65 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 67 cast_environment_->logger()->Unsubscribe(&event_subscriber_); | 66 cast_environment_->logger()->Unsubscribe(&event_subscriber_); |
| 68 } | 67 } |
| 69 | 68 |
| 70 void FrameReceiver::RequestEncodedFrame( | 69 void FrameReceiver::RequestEncodedFrame( |
| 71 const ReceiveEncodedFrameCallback& callback) { | 70 const ReceiveEncodedFrameCallback& callback) { |
| 72 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 71 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 85 size_t payload_size; | 84 size_t payload_size; |
| 86 if (!packet_parser_.ParsePacket(&packet->front(), | 85 if (!packet_parser_.ParsePacket(&packet->front(), |
| 87 packet->size(), | 86 packet->size(), |
| 88 &rtp_header, | 87 &rtp_header, |
| 89 &payload_data, | 88 &payload_data, |
| 90 &payload_size)) { | 89 &payload_size)) { |
| 91 return false; | 90 return false; |
| 92 } | 91 } |
| 93 | 92 |
| 94 ProcessParsedPacket(rtp_header, payload_data, payload_size); | 93 ProcessParsedPacket(rtp_header, payload_data, payload_size); |
| 95 stats_.UpdateStatistics(rtp_header); | 94 stats_.UpdateStatistics(rtp_header, rtp_timebase_); |
| 96 } | 95 } |
| 97 | 96 |
| 98 if (!reports_are_scheduled_) { | 97 if (!reports_are_scheduled_) { |
| 99 ScheduleNextRtcpReport(); | 98 ScheduleNextRtcpReport(); |
| 100 ScheduleNextCastMessage(); | 99 ScheduleNextCastMessage(); |
| 101 reports_are_scheduled_ = true; | 100 reports_are_scheduled_ = true; |
| 102 } | 101 } |
| 103 | 102 |
| 104 return true; | 103 return true; |
| 105 } | 104 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 129 const bool complete = | 128 const bool complete = |
| 130 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); | 129 framer_.InsertPacket(payload_data, payload_size, rtp_header, &duplicate); |
| 131 | 130 |
| 132 // Duplicate packets are ignored. | 131 // Duplicate packets are ignored. |
| 133 if (duplicate) | 132 if (duplicate) |
| 134 return; | 133 return; |
| 135 | 134 |
| 136 // Update lip-sync values upon receiving the first packet of each frame, or if | 135 // Update lip-sync values upon receiving the first packet of each frame, or if |
| 137 // they have never been set yet. | 136 // they have never been set yet. |
| 138 if (rtp_header.packet_id == 0 || lip_sync_reference_time_.is_null()) { | 137 if (rtp_header.packet_id == 0 || lip_sync_reference_time_.is_null()) { |
| 139 RtpTimestamp fresh_sync_rtp; | 138 RtpTimeTicks fresh_sync_rtp; |
| 140 base::TimeTicks fresh_sync_reference; | 139 base::TimeTicks fresh_sync_reference; |
| 141 if (!rtcp_.GetLatestLipSyncTimes(&fresh_sync_rtp, &fresh_sync_reference)) { | 140 if (!rtcp_.GetLatestLipSyncTimes(&fresh_sync_rtp, &fresh_sync_reference)) { |
| 142 // HACK: The sender should have provided Sender Reports before the first | 141 // HACK: The sender should have provided Sender Reports before the first |
| 143 // frame was sent. However, the spec does not currently require this. | 142 // frame was sent. However, the spec does not currently require this. |
| 144 // Therefore, when the data is missing, the local clock is used to | 143 // Therefore, when the data is missing, the local clock is used to |
| 145 // generate reference timestamps. | 144 // generate reference timestamps. |
| 146 VLOG(2) << "Lip sync info missing. Falling-back to local clock."; | 145 VLOG(2) << "Lip sync info missing. Falling-back to local clock."; |
| 147 fresh_sync_rtp = rtp_header.rtp_timestamp; | 146 fresh_sync_rtp = rtp_header.rtp_timestamp; |
| 148 fresh_sync_reference = now; | 147 fresh_sync_reference = now; |
| 149 } | 148 } |
| 150 // |lip_sync_reference_time_| is always incremented according to the time | 149 // |lip_sync_reference_time_| is always incremented according to the time |
| 151 // delta computed from the difference in RTP timestamps. Then, | 150 // delta computed from the difference in RTP timestamps. Then, |
| 152 // |lip_sync_drift_| accounts for clock drift and also smoothes-out any | 151 // |lip_sync_drift_| accounts for clock drift and also smoothes-out any |
| 153 // sudden/discontinuous shifts in the series of reference time values. | 152 // sudden/discontinuous shifts in the series of reference time values. |
| 154 if (lip_sync_reference_time_.is_null()) { | 153 if (lip_sync_reference_time_.is_null()) { |
| 155 lip_sync_reference_time_ = fresh_sync_reference; | 154 lip_sync_reference_time_ = fresh_sync_reference; |
| 156 } else { | 155 } else { |
| 157 lip_sync_reference_time_ += RtpDeltaToTimeDelta( | 156 // Note: It's okay for the conversion ToTimeDelta() to be approximate |
| 158 static_cast<int32>(fresh_sync_rtp - lip_sync_rtp_timestamp_), | 157 // because |lip_sync_drift_| will account for accumulated errors. |
| 159 rtp_timebase_); | 158 lip_sync_reference_time_ += |
| 159 (fresh_sync_rtp - lip_sync_rtp_timestamp_).ToTimeDelta(rtp_timebase_); |
| 160 } | 160 } |
| 161 lip_sync_rtp_timestamp_ = fresh_sync_rtp; | 161 lip_sync_rtp_timestamp_ = fresh_sync_rtp; |
| 162 lip_sync_drift_.Update( | 162 lip_sync_drift_.Update( |
| 163 now, fresh_sync_reference - lip_sync_reference_time_); | 163 now, fresh_sync_reference - lip_sync_reference_time_); |
| 164 } | 164 } |
| 165 | 165 |
| 166 // Another frame is complete from a non-duplicate packet. Attempt to emit | 166 // Another frame is complete from a non-duplicate packet. Attempt to emit |
| 167 // more frames to satisfy enqueued requests. | 167 // more frames to satisfy enqueued requests. |
| 168 if (complete) | 168 if (complete) |
| 169 EmitAvailableEncodedFrames(); | 169 EmitAvailableEncodedFrames(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 void FrameReceiver::CastFeedback(const RtcpCastMessage& cast_message) { | 172 void FrameReceiver::CastFeedback(const RtcpCastMessage& cast_message) { |
| 173 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 173 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 174 | 174 |
| 175 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 175 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 176 RtpTimestamp rtp_timestamp = | 176 RtpTimeTicks rtp_timestamp = |
| 177 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id & 0xff]; | 177 frame_id_to_rtp_timestamp_[cast_message.ack_frame_id & 0xff]; |
| 178 | 178 |
| 179 scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); | 179 scoped_ptr<FrameEvent> ack_sent_event(new FrameEvent()); |
| 180 ack_sent_event->timestamp = now; | 180 ack_sent_event->timestamp = now; |
| 181 ack_sent_event->type = FRAME_ACK_SENT; | 181 ack_sent_event->type = FRAME_ACK_SENT; |
| 182 ack_sent_event->media_type = event_media_type_; | 182 ack_sent_event->media_type = event_media_type_; |
| 183 ack_sent_event->rtp_timestamp = rtp_timestamp; | 183 ack_sent_event->rtp_timestamp = rtp_timestamp; |
| 184 ack_sent_event->frame_id = cast_message.ack_frame_id; | 184 ack_sent_event->frame_id = cast_message.ack_frame_id; |
| 185 cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); | 185 cast_environment_->logger()->DispatchFrameEvent(ack_sent_event.Pass()); |
| 186 | 186 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 if (!callback.is_null()) | 295 if (!callback.is_null()) |
| 296 callback.Run(encoded_frame.Pass()); | 296 callback.Run(encoded_frame.Pass()); |
| 297 } | 297 } |
| 298 | 298 |
| 299 base::TimeTicks FrameReceiver::GetPlayoutTime(const EncodedFrame& frame) const { | 299 base::TimeTicks FrameReceiver::GetPlayoutTime(const EncodedFrame& frame) const { |
| 300 base::TimeDelta target_playout_delay = target_playout_delay_; | 300 base::TimeDelta target_playout_delay = target_playout_delay_; |
| 301 if (frame.new_playout_delay_ms) { | 301 if (frame.new_playout_delay_ms) { |
| 302 target_playout_delay = base::TimeDelta::FromMilliseconds( | 302 target_playout_delay = base::TimeDelta::FromMilliseconds( |
| 303 frame.new_playout_delay_ms); | 303 frame.new_playout_delay_ms); |
| 304 } | 304 } |
| 305 return lip_sync_reference_time_ + | 305 return lip_sync_reference_time_ + lip_sync_drift_.Current() + |
| 306 lip_sync_drift_.Current() + | 306 (frame.rtp_timestamp - lip_sync_rtp_timestamp_) |
| 307 RtpDeltaToTimeDelta( | 307 .ToTimeDelta(rtp_timebase_) + |
| 308 static_cast<int32>(frame.rtp_timestamp - lip_sync_rtp_timestamp_), | 308 target_playout_delay; |
| 309 rtp_timebase_) + | |
| 310 target_playout_delay; | |
| 311 } | 309 } |
| 312 | 310 |
| 313 void FrameReceiver::ScheduleNextCastMessage() { | 311 void FrameReceiver::ScheduleNextCastMessage() { |
| 314 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 312 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 315 base::TimeTicks send_time; | 313 base::TimeTicks send_time; |
| 316 framer_.TimeToSendNextCastMessage(&send_time); | 314 framer_.TimeToSendNextCastMessage(&send_time); |
| 317 base::TimeDelta time_to_send = | 315 base::TimeDelta time_to_send = |
| 318 send_time - cast_environment_->Clock()->NowTicks(); | 316 send_time - cast_environment_->Clock()->NowTicks(); |
| 319 time_to_send = std::max( | 317 time_to_send = std::max( |
| 320 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 318 time_to_send, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 351 rtcp_.ConvertToNTPAndSave(now), | 349 rtcp_.ConvertToNTPAndSave(now), |
| 352 NULL, | 350 NULL, |
| 353 base::TimeDelta(), | 351 base::TimeDelta(), |
| 354 NULL, | 352 NULL, |
| 355 &stats); | 353 &stats); |
| 356 ScheduleNextRtcpReport(); | 354 ScheduleNextRtcpReport(); |
| 357 } | 355 } |
| 358 | 356 |
| 359 } // namespace cast | 357 } // namespace cast |
| 360 } // namespace media | 358 } // namespace media |
| OLD | NEW |