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