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/sender/frame_sender.h" | 5 #include "media/cast/sender/frame_sender.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 DCHECK_GT(rtp_timebase_, 0); | 65 DCHECK_GT(rtp_timebase_, 0); |
66 DCHECK(congestion_control_); | 66 DCHECK(congestion_control_); |
67 // We assume animated content to begin with since that is the common use | 67 // We assume animated content to begin with since that is the common use |
68 // case today. | 68 // case today. |
69 VLOG(1) << SENDER_SSRC << "min latency " | 69 VLOG(1) << SENDER_SSRC << "min latency " |
70 << min_playout_delay_.InMilliseconds() << "max latency " | 70 << min_playout_delay_.InMilliseconds() << "max latency " |
71 << max_playout_delay.InMilliseconds() << "animated latency " | 71 << max_playout_delay.InMilliseconds() << "animated latency " |
72 << animated_playout_delay.InMilliseconds(); | 72 << animated_playout_delay.InMilliseconds(); |
73 SetTargetPlayoutDelay(animated_playout_delay_); | 73 SetTargetPlayoutDelay(animated_playout_delay_); |
74 send_target_playout_delay_ = false; | 74 send_target_playout_delay_ = false; |
75 memset(frame_rtp_timestamps_, 0, sizeof(frame_rtp_timestamps_)); | |
76 } | 75 } |
77 | 76 |
78 FrameSender::~FrameSender() { | 77 FrameSender::~FrameSender() { |
79 } | 78 } |
80 | 79 |
81 void FrameSender::ScheduleNextRtcpReport() { | 80 void FrameSender::ScheduleNextRtcpReport() { |
82 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 81 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
83 | 82 |
84 cast_environment_->PostDelayedTask( | 83 cast_environment_->PostDelayedTask( |
85 CastEnvironment::MAIN, FROM_HERE, | 84 CastEnvironment::MAIN, FROM_HERE, |
(...skipping 10 matching lines...) Expand all Loading... |
96 | 95 |
97 // Create lip-sync info for the sender report. The last sent frame's | 96 // Create lip-sync info for the sender report. The last sent frame's |
98 // reference time and RTP timestamp are used to estimate an RTP timestamp in | 97 // reference time and RTP timestamp are used to estimate an RTP timestamp in |
99 // terms of "now." Note that |now| is never likely to be precise to an exact | 98 // terms of "now." Note that |now| is never likely to be precise to an exact |
100 // frame boundary; and so the computation here will result in a | 99 // frame boundary; and so the computation here will result in a |
101 // |now_as_rtp_timestamp| value that is rarely equal to any one emitted by the | 100 // |now_as_rtp_timestamp| value that is rarely equal to any one emitted by the |
102 // encoder. | 101 // encoder. |
103 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 102 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
104 const base::TimeDelta time_delta = | 103 const base::TimeDelta time_delta = |
105 now - GetRecordedReferenceTime(last_sent_frame_id_); | 104 now - GetRecordedReferenceTime(last_sent_frame_id_); |
106 const int64_t rtp_delta = TimeDeltaToRtpDelta(time_delta, rtp_timebase_); | 105 const RtpTimeDelta rtp_delta = |
107 const uint32_t now_as_rtp_timestamp = | 106 RtpTimeDelta::FromTimeDelta(time_delta, rtp_timebase_); |
108 GetRecordedRtpTimestamp(last_sent_frame_id_) + | 107 const RtpTimeTicks now_as_rtp_timestamp = |
109 static_cast<uint32_t>(rtp_delta); | 108 GetRecordedRtpTimestamp(last_sent_frame_id_) + rtp_delta; |
110 transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp); | 109 transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp); |
111 | 110 |
112 if (schedule_future_reports) | 111 if (schedule_future_reports) |
113 ScheduleNextRtcpReport(); | 112 ScheduleNextRtcpReport(); |
114 } | 113 } |
115 | 114 |
116 void FrameSender::OnMeasuredRoundTripTime(base::TimeDelta rtt) { | 115 void FrameSender::OnMeasuredRoundTripTime(base::TimeDelta rtt) { |
117 DCHECK(rtt > base::TimeDelta()); | 116 DCHECK(rtt > base::TimeDelta()); |
118 current_round_trip_time_ = rtt; | 117 current_round_trip_time_ = rtt; |
119 } | 118 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 171 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
173 DCHECK(!last_send_time_.is_null()); | 172 DCHECK(!last_send_time_.is_null()); |
174 VLOG(1) << SENDER_SSRC << "Resending last packet of frame " | 173 VLOG(1) << SENDER_SSRC << "Resending last packet of frame " |
175 << last_sent_frame_id_ << " to kick-start."; | 174 << last_sent_frame_id_ << " to kick-start."; |
176 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 175 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
177 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); | 176 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); |
178 } | 177 } |
179 | 178 |
180 void FrameSender::RecordLatestFrameTimestamps(uint32_t frame_id, | 179 void FrameSender::RecordLatestFrameTimestamps(uint32_t frame_id, |
181 base::TimeTicks reference_time, | 180 base::TimeTicks reference_time, |
182 RtpTimestamp rtp_timestamp) { | 181 RtpTimeTicks rtp_timestamp) { |
183 DCHECK(!reference_time.is_null()); | 182 DCHECK(!reference_time.is_null()); |
184 frame_reference_times_[frame_id % arraysize(frame_reference_times_)] = | 183 frame_reference_times_[frame_id % arraysize(frame_reference_times_)] = |
185 reference_time; | 184 reference_time; |
186 frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)] = | 185 frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)] = |
187 rtp_timestamp; | 186 rtp_timestamp; |
188 } | 187 } |
189 | 188 |
190 base::TimeTicks FrameSender::GetRecordedReferenceTime(uint32_t frame_id) const { | 189 base::TimeTicks FrameSender::GetRecordedReferenceTime(uint32_t frame_id) const { |
191 return frame_reference_times_[frame_id % arraysize(frame_reference_times_)]; | 190 return frame_reference_times_[frame_id % arraysize(frame_reference_times_)]; |
192 } | 191 } |
193 | 192 |
194 RtpTimestamp FrameSender::GetRecordedRtpTimestamp(uint32_t frame_id) const { | 193 RtpTimeTicks FrameSender::GetRecordedRtpTimestamp(uint32_t frame_id) const { |
195 return frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)]; | 194 return frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)]; |
196 } | 195 } |
197 | 196 |
198 int FrameSender::GetUnacknowledgedFrameCount() const { | 197 int FrameSender::GetUnacknowledgedFrameCount() const { |
199 const int count = | 198 const int count = |
200 static_cast<int32_t>(last_sent_frame_id_ - latest_acked_frame_id_); | 199 static_cast<int32_t>(last_sent_frame_id_ - latest_acked_frame_id_); |
201 DCHECK_GE(count, 0); | 200 DCHECK_GE(count, 0); |
202 return count; | 201 return count; |
203 } | 202 } |
204 | 203 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 | 249 |
251 RecordLatestFrameTimestamps(frame_id, | 250 RecordLatestFrameTimestamps(frame_id, |
252 encoded_frame->reference_time, | 251 encoded_frame->reference_time, |
253 encoded_frame->rtp_timestamp); | 252 encoded_frame->rtp_timestamp); |
254 | 253 |
255 if (!is_audio_) { | 254 if (!is_audio_) { |
256 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 255 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
257 TRACE_EVENT_INSTANT1( | 256 TRACE_EVENT_INSTANT1( |
258 "cast_perf_test", "VideoFrameEncoded", | 257 "cast_perf_test", "VideoFrameEncoded", |
259 TRACE_EVENT_SCOPE_THREAD, | 258 TRACE_EVENT_SCOPE_THREAD, |
260 "rtp_timestamp", encoded_frame->rtp_timestamp); | 259 "rtp_timestamp", encoded_frame->rtp_timestamp.lower_32_bits()); |
261 } | 260 } |
262 | 261 |
263 // At the start of the session, it's important to send reports before each | 262 // At the start of the session, it's important to send reports before each |
264 // frame so that the receiver can properly compute playout times. The reason | 263 // frame so that the receiver can properly compute playout times. The reason |
265 // more than one report is sent is because transmission is not guaranteed, | 264 // more than one report is sent is because transmission is not guaranteed, |
266 // only best effort, so send enough that one should almost certainly get | 265 // only best effort, so send enough that one should almost certainly get |
267 // through. | 266 // through. |
268 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 267 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
269 // SendRtcpReport() will schedule future reports to be made if this is the | 268 // SendRtcpReport() will schedule future reports to be made if this is the |
270 // last "aggressive report." | 269 // last "aggressive report." |
271 ++num_aggressive_rtcp_reports_sent_; | 270 ++num_aggressive_rtcp_reports_sent_; |
272 const bool is_last_aggressive_report = | 271 const bool is_last_aggressive_report = |
273 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); | 272 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); |
274 VLOG_IF(1, is_last_aggressive_report) | 273 VLOG_IF(1, is_last_aggressive_report) |
275 << SENDER_SSRC << "Sending last aggressive report."; | 274 << SENDER_SSRC << "Sending last aggressive report."; |
276 SendRtcpReport(is_last_aggressive_report); | 275 SendRtcpReport(is_last_aggressive_report); |
277 } | 276 } |
278 | 277 |
279 congestion_control_->SendFrameToTransport( | 278 congestion_control_->SendFrameToTransport( |
280 frame_id, encoded_frame->data.size() * 8, last_send_time_); | 279 frame_id, encoded_frame->data.size() * 8, last_send_time_); |
281 | 280 |
282 if (send_target_playout_delay_) { | 281 if (send_target_playout_delay_) { |
283 encoded_frame->new_playout_delay_ms = | 282 encoded_frame->new_playout_delay_ms = |
284 target_playout_delay_.InMilliseconds(); | 283 target_playout_delay_.InMilliseconds(); |
285 } | 284 } |
286 | 285 |
287 TRACE_EVENT_ASYNC_BEGIN1("cast.stream", | 286 TRACE_EVENT_ASYNC_BEGIN1("cast.stream", |
288 is_audio_ ? "Audio Transport" : "Video Transport", | 287 is_audio_ ? "Audio Transport" : "Video Transport", |
289 frame_id, | 288 frame_id, |
290 "rtp_timestamp", encoded_frame->rtp_timestamp); | 289 "rtp_timestamp", encoded_frame->rtp_timestamp.lower_32_bits()); |
291 transport_sender_->InsertFrame(ssrc_, *encoded_frame); | 290 transport_sender_->InsertFrame(ssrc_, *encoded_frame); |
292 } | 291 } |
293 | 292 |
294 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { | 293 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { |
295 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 294 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
296 | 295 |
297 const bool have_valid_rtt = current_round_trip_time_ > base::TimeDelta(); | 296 const bool have_valid_rtt = current_round_trip_time_ > base::TimeDelta(); |
298 if (have_valid_rtt) { | 297 if (have_valid_rtt) { |
299 congestion_control_->UpdateRtt(current_round_trip_time_); | 298 congestion_control_->UpdateRtt(current_round_trip_time_); |
300 | 299 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; | 420 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; |
422 return true; | 421 return true; |
423 } | 422 } |
424 | 423 |
425 // Next frame is accepted. | 424 // Next frame is accepted. |
426 return false; | 425 return false; |
427 } | 426 } |
428 | 427 |
429 } // namespace cast | 428 } // namespace cast |
430 } // namespace media | 429 } // namespace media |
OLD | NEW |