| 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 <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
| 10 #include "media/cast/cast_defines.h" | 10 #include "media/cast/cast_defines.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 duplicate_ack_counter_(0), | 51 duplicate_ack_counter_(0), |
| 52 congestion_control_(congestion_control), | 52 congestion_control_(congestion_control), |
| 53 rtp_timebase_(rtp_timebase), | 53 rtp_timebase_(rtp_timebase), |
| 54 is_audio_(is_audio), | 54 is_audio_(is_audio), |
| 55 weak_factory_(this) { | 55 weak_factory_(this) { |
| 56 DCHECK(transport_sender_); | 56 DCHECK(transport_sender_); |
| 57 DCHECK_GT(rtp_timebase_, 0); | 57 DCHECK_GT(rtp_timebase_, 0); |
| 58 DCHECK(congestion_control_); | 58 DCHECK(congestion_control_); |
| 59 SetTargetPlayoutDelay(min_playout_delay_); | 59 SetTargetPlayoutDelay(min_playout_delay_); |
| 60 send_target_playout_delay_ = false; | 60 send_target_playout_delay_ = false; |
| 61 memset(frame_rtp_timestamps_, 0, sizeof(frame_rtp_timestamps_)); | |
| 62 } | 61 } |
| 63 | 62 |
| 64 FrameSender::~FrameSender() { | 63 FrameSender::~FrameSender() { |
| 65 } | 64 } |
| 66 | 65 |
| 67 void FrameSender::ScheduleNextRtcpReport() { | 66 void FrameSender::ScheduleNextRtcpReport() { |
| 68 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 67 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 69 | 68 |
| 70 cast_environment_->PostDelayedTask( | 69 cast_environment_->PostDelayedTask( |
| 71 CastEnvironment::MAIN, FROM_HERE, | 70 CastEnvironment::MAIN, FROM_HERE, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 82 | 81 |
| 83 // Create lip-sync info for the sender report. The last sent frame's | 82 // Create lip-sync info for the sender report. The last sent frame's |
| 84 // reference time and RTP timestamp are used to estimate an RTP timestamp in | 83 // reference time and RTP timestamp are used to estimate an RTP timestamp in |
| 85 // terms of "now." Note that |now| is never likely to be precise to an exact | 84 // terms of "now." Note that |now| is never likely to be precise to an exact |
| 86 // frame boundary; and so the computation here will result in a | 85 // frame boundary; and so the computation here will result in a |
| 87 // |now_as_rtp_timestamp| value that is rarely equal to any one emitted by the | 86 // |now_as_rtp_timestamp| value that is rarely equal to any one emitted by the |
| 88 // encoder. | 87 // encoder. |
| 89 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 88 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 90 const base::TimeDelta time_delta = | 89 const base::TimeDelta time_delta = |
| 91 now - GetRecordedReferenceTime(last_sent_frame_id_); | 90 now - GetRecordedReferenceTime(last_sent_frame_id_); |
| 92 const int64_t rtp_delta = TimeDeltaToRtpDelta(time_delta, rtp_timebase_); | 91 const RtpTimeDelta rtp_delta = |
| 93 const uint32_t now_as_rtp_timestamp = | 92 RtpTimeDelta::FromTimeDelta(time_delta, rtp_timebase_); |
| 94 GetRecordedRtpTimestamp(last_sent_frame_id_) + | 93 const RtpTimeTicks now_as_rtp_timestamp = |
| 95 static_cast<uint32_t>(rtp_delta); | 94 GetRecordedRtpTimestamp(last_sent_frame_id_) + rtp_delta; |
| 96 transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp); | 95 transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp); |
| 97 | 96 |
| 98 if (schedule_future_reports) | 97 if (schedule_future_reports) |
| 99 ScheduleNextRtcpReport(); | 98 ScheduleNextRtcpReport(); |
| 100 } | 99 } |
| 101 | 100 |
| 102 void FrameSender::OnMeasuredRoundTripTime(base::TimeDelta rtt) { | 101 void FrameSender::OnMeasuredRoundTripTime(base::TimeDelta rtt) { |
| 103 DCHECK(rtt > base::TimeDelta()); | 102 DCHECK(rtt > base::TimeDelta()); |
| 104 current_round_trip_time_ = rtt; | 103 current_round_trip_time_ = rtt; |
| 105 } | 104 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 157 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 159 DCHECK(!last_send_time_.is_null()); | 158 DCHECK(!last_send_time_.is_null()); |
| 160 VLOG(1) << SENDER_SSRC << "Resending last packet of frame " | 159 VLOG(1) << SENDER_SSRC << "Resending last packet of frame " |
| 161 << last_sent_frame_id_ << " to kick-start."; | 160 << last_sent_frame_id_ << " to kick-start."; |
| 162 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 161 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 163 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); | 162 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); |
| 164 } | 163 } |
| 165 | 164 |
| 166 void FrameSender::RecordLatestFrameTimestamps(uint32_t frame_id, | 165 void FrameSender::RecordLatestFrameTimestamps(uint32_t frame_id, |
| 167 base::TimeTicks reference_time, | 166 base::TimeTicks reference_time, |
| 168 RtpTimestamp rtp_timestamp) { | 167 RtpTimeTicks rtp_timestamp) { |
| 169 DCHECK(!reference_time.is_null()); | 168 DCHECK(!reference_time.is_null()); |
| 170 frame_reference_times_[frame_id % arraysize(frame_reference_times_)] = | 169 frame_reference_times_[frame_id % arraysize(frame_reference_times_)] = |
| 171 reference_time; | 170 reference_time; |
| 172 frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)] = | 171 frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)] = |
| 173 rtp_timestamp; | 172 rtp_timestamp; |
| 174 } | 173 } |
| 175 | 174 |
| 176 base::TimeTicks FrameSender::GetRecordedReferenceTime(uint32_t frame_id) const { | 175 base::TimeTicks FrameSender::GetRecordedReferenceTime(uint32_t frame_id) const { |
| 177 return frame_reference_times_[frame_id % arraysize(frame_reference_times_)]; | 176 return frame_reference_times_[frame_id % arraysize(frame_reference_times_)]; |
| 178 } | 177 } |
| 179 | 178 |
| 180 RtpTimestamp FrameSender::GetRecordedRtpTimestamp(uint32_t frame_id) const { | 179 RtpTimeTicks FrameSender::GetRecordedRtpTimestamp(uint32_t frame_id) const { |
| 181 return frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)]; | 180 return frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)]; |
| 182 } | 181 } |
| 183 | 182 |
| 184 int FrameSender::GetUnacknowledgedFrameCount() const { | 183 int FrameSender::GetUnacknowledgedFrameCount() const { |
| 185 const int count = | 184 const int count = |
| 186 static_cast<int32_t>(last_sent_frame_id_ - latest_acked_frame_id_); | 185 static_cast<int32_t>(last_sent_frame_id_ - latest_acked_frame_id_); |
| 187 DCHECK_GE(count, 0); | 186 DCHECK_GE(count, 0); |
| 188 return count; | 187 return count; |
| 189 } | 188 } |
| 190 | 189 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 | 235 |
| 237 RecordLatestFrameTimestamps(frame_id, | 236 RecordLatestFrameTimestamps(frame_id, |
| 238 encoded_frame->reference_time, | 237 encoded_frame->reference_time, |
| 239 encoded_frame->rtp_timestamp); | 238 encoded_frame->rtp_timestamp); |
| 240 | 239 |
| 241 if (!is_audio_) { | 240 if (!is_audio_) { |
| 242 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 241 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 243 TRACE_EVENT_INSTANT1( | 242 TRACE_EVENT_INSTANT1( |
| 244 "cast_perf_test", "VideoFrameEncoded", | 243 "cast_perf_test", "VideoFrameEncoded", |
| 245 TRACE_EVENT_SCOPE_THREAD, | 244 TRACE_EVENT_SCOPE_THREAD, |
| 246 "rtp_timestamp", encoded_frame->rtp_timestamp); | 245 "rtp_timestamp", encoded_frame->rtp_timestamp.lower_32_bits()); |
| 247 } | 246 } |
| 248 | 247 |
| 249 // At the start of the session, it's important to send reports before each | 248 // At the start of the session, it's important to send reports before each |
| 250 // frame so that the receiver can properly compute playout times. The reason | 249 // frame so that the receiver can properly compute playout times. The reason |
| 251 // more than one report is sent is because transmission is not guaranteed, | 250 // more than one report is sent is because transmission is not guaranteed, |
| 252 // only best effort, so send enough that one should almost certainly get | 251 // only best effort, so send enough that one should almost certainly get |
| 253 // through. | 252 // through. |
| 254 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 253 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
| 255 // SendRtcpReport() will schedule future reports to be made if this is the | 254 // SendRtcpReport() will schedule future reports to be made if this is the |
| 256 // last "aggressive report." | 255 // last "aggressive report." |
| 257 ++num_aggressive_rtcp_reports_sent_; | 256 ++num_aggressive_rtcp_reports_sent_; |
| 258 const bool is_last_aggressive_report = | 257 const bool is_last_aggressive_report = |
| 259 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); | 258 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); |
| 260 VLOG_IF(1, is_last_aggressive_report) | 259 VLOG_IF(1, is_last_aggressive_report) |
| 261 << SENDER_SSRC << "Sending last aggressive report."; | 260 << SENDER_SSRC << "Sending last aggressive report."; |
| 262 SendRtcpReport(is_last_aggressive_report); | 261 SendRtcpReport(is_last_aggressive_report); |
| 263 } | 262 } |
| 264 | 263 |
| 265 congestion_control_->SendFrameToTransport( | 264 congestion_control_->SendFrameToTransport( |
| 266 frame_id, encoded_frame->data.size() * 8, last_send_time_); | 265 frame_id, encoded_frame->data.size() * 8, last_send_time_); |
| 267 | 266 |
| 268 if (send_target_playout_delay_) { | 267 if (send_target_playout_delay_) { |
| 269 encoded_frame->new_playout_delay_ms = | 268 encoded_frame->new_playout_delay_ms = |
| 270 target_playout_delay_.InMilliseconds(); | 269 target_playout_delay_.InMilliseconds(); |
| 271 } | 270 } |
| 272 | 271 |
| 273 TRACE_EVENT_ASYNC_BEGIN1("cast.stream", | 272 TRACE_EVENT_ASYNC_BEGIN1("cast.stream", |
| 274 is_audio_ ? "Audio Transport" : "Video Transport", | 273 is_audio_ ? "Audio Transport" : "Video Transport", |
| 275 frame_id, | 274 frame_id, |
| 276 "rtp_timestamp", encoded_frame->rtp_timestamp); | 275 "rtp_timestamp", encoded_frame->rtp_timestamp.lower_32_bits()); |
| 277 transport_sender_->InsertFrame(ssrc_, *encoded_frame); | 276 transport_sender_->InsertFrame(ssrc_, *encoded_frame); |
| 278 } | 277 } |
| 279 | 278 |
| 280 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { | 279 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { |
| 281 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 280 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 282 | 281 |
| 283 const bool have_valid_rtt = current_round_trip_time_ > base::TimeDelta(); | 282 const bool have_valid_rtt = current_round_trip_time_ > base::TimeDelta(); |
| 284 if (have_valid_rtt) { | 283 if (have_valid_rtt) { |
| 285 congestion_control_->UpdateRtt(current_round_trip_time_); | 284 congestion_control_->UpdateRtt(current_round_trip_time_); |
| 286 | 285 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; | 406 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; |
| 408 return true; | 407 return true; |
| 409 } | 408 } |
| 410 | 409 |
| 411 // Next frame is accepted. | 410 // Next frame is accepted. |
| 412 return false; | 411 return false; |
| 413 } | 412 } |
| 414 | 413 |
| 415 } // namespace cast | 414 } // namespace cast |
| 416 } // namespace media | 415 } // namespace media |
| OLD | NEW |