| Index: media/cast/video_sender/video_sender.cc
|
| diff --git a/media/cast/video_sender/video_sender.cc b/media/cast/video_sender/video_sender.cc
|
| index 708bb424a74866d42758ad93993520f76ad23924..57b8ea729915b9d21b04736bd96833ef5610ee04 100644
|
| --- a/media/cast/video_sender/video_sender.cc
|
| +++ b/media/cast/video_sender/video_sender.cc
|
| @@ -20,23 +20,8 @@
|
| namespace media {
|
| namespace cast {
|
|
|
| -const int64 kMinSchedulingDelayMs = 1;
|
| -
|
| -class LocalRtcpVideoSenderFeedback : public RtcpSenderFeedback {
|
| - public:
|
| - explicit LocalRtcpVideoSenderFeedback(VideoSender* video_sender)
|
| - : video_sender_(video_sender) {}
|
| -
|
| - virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback)
|
| - OVERRIDE {
|
| - video_sender_->OnReceivedCastFeedback(cast_feedback);
|
| - }
|
| -
|
| - private:
|
| - VideoSender* video_sender_;
|
| -
|
| - DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtcpVideoSenderFeedback);
|
| -};
|
| +const int kNumAggressiveReportsSentAtStart = 100;
|
| +const int kMinSchedulingDelayMs = 1;
|
|
|
| VideoSender::VideoSender(
|
| scoped_refptr<CastEnvironment> cast_environment,
|
| @@ -51,7 +36,7 @@ VideoSender::VideoSender(
|
| cast_environment_(cast_environment),
|
| transport_sender_(transport_sender),
|
| rtp_timestamp_helper_(kVideoFrequency),
|
| - rtcp_feedback_(new LocalRtcpVideoSenderFeedback(this)),
|
| + num_aggressive_rtcp_reports_sent_(0),
|
| last_acked_frame_id_(-1),
|
| last_sent_frame_id_(-1),
|
| frames_in_encoder_(0),
|
| @@ -91,7 +76,7 @@ VideoSender::VideoSender(
|
|
|
| rtcp_.reset(
|
| new Rtcp(cast_environment_,
|
| - rtcp_feedback_.get(),
|
| + this,
|
| transport_sender_,
|
| NULL, // paced sender.
|
| NULL,
|
| @@ -189,6 +174,22 @@ void VideoSender::SendEncodedVideoFrameMainThread(
|
| DCHECK(!encoded_frame->reference_time.is_null());
|
| rtp_timestamp_helper_.StoreLatestTime(encoded_frame->reference_time,
|
| encoded_frame->rtp_timestamp);
|
| +
|
| + // At the start of the session, it's important to send reports before each
|
| + // frame so that the receiver can properly compute playout times. The reason
|
| + // more than one report is sent is because transmission is not guaranteed,
|
| + // only best effort, so send enough that one should almost certainly get
|
| + // through.
|
| + if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
|
| + // SendRtcpReport() will schedule future reports to be made if this is the
|
| + // last "aggressive report."
|
| + ++num_aggressive_rtcp_reports_sent_;
|
| + const bool is_last_aggressive_report =
|
| + (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart);
|
| + VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report.";
|
| + SendRtcpReport(is_last_aggressive_report);
|
| + }
|
| +
|
| transport_sender_->InsertCodedVideoFrame(*encoded_frame);
|
| UpdateFramesInFlight();
|
| InitializeTimers();
|
| @@ -210,19 +211,25 @@ void VideoSender::ScheduleNextRtcpReport() {
|
| cast_environment_->PostDelayedTask(
|
| CastEnvironment::MAIN,
|
| FROM_HERE,
|
| - base::Bind(&VideoSender::SendRtcpReport, weak_factory_.GetWeakPtr()),
|
| + base::Bind(&VideoSender::SendRtcpReport,
|
| + weak_factory_.GetWeakPtr(),
|
| + true),
|
| time_to_next);
|
| }
|
|
|
| -void VideoSender::SendRtcpReport() {
|
| +void VideoSender::SendRtcpReport(bool schedule_future_reports) {
|
| DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
|
| uint32 now_as_rtp_timestamp = 0;
|
| if (rtp_timestamp_helper_.GetCurrentTimeAsRtpTimestamp(
|
| now, &now_as_rtp_timestamp)) {
|
| rtcp_->SendRtcpFromRtpSender(now, now_as_rtp_timestamp);
|
| + } else {
|
| + // |rtp_timestamp_helper_| should have stored a mapping by this point.
|
| + NOTREACHED();
|
| }
|
| - ScheduleNextRtcpReport();
|
| + if (schedule_future_reports)
|
| + ScheduleNextRtcpReport();
|
| }
|
|
|
| void VideoSender::ScheduleNextResendCheck() {
|
| @@ -313,6 +320,16 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
|
| if (rtcp_->Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt)) {
|
| // Don't use a RTT lower than our average.
|
| rtt = std::max(rtt, avg_rtt);
|
| +
|
| + // Having the RTT values implies the receiver sent back a receiver report
|
| + // based on it having received a report from here. Therefore, ensure this
|
| + // sender stops aggressively sending reports.
|
| + if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
|
| + VLOG(1) << "No longer a need to send reports aggressively (sent "
|
| + << num_aggressive_rtcp_reports_sent_ << ").";
|
| + num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart;
|
| + ScheduleNextRtcpReport();
|
| + }
|
| } else {
|
| // We have no measured value use default.
|
| rtt = base::TimeDelta::FromMilliseconds(kStartRttMs);
|
| @@ -368,11 +385,6 @@ void VideoSender::ReceivedAck(uint32 acked_frame_id) {
|
| // be acked. Ignore.
|
| return;
|
| }
|
| - // Start sending RTCP packets only after receiving the first ACK, i.e. only
|
| - // after establishing that the receiver is active.
|
| - if (last_acked_frame_id_ == -1) {
|
| - ScheduleNextRtcpReport();
|
| - }
|
| last_acked_frame_id_ = static_cast<int>(acked_frame_id);
|
| base::TimeTicks now = cast_environment_->Clock()->NowTicks();
|
|
|
|
|