[SyncFS] Initialize SyncWorker when sync is enabled.
[chromium-blink-merge.git] / media / cast / sender / frame_sender.cc
blobf338dd9b2b065ce91a7ea98332711478916ff16f
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
3 // found in the LICENSE file.
5 #include "media/cast/sender/frame_sender.h"
7 namespace media {
8 namespace cast {
9 namespace {
10 const int kMinSchedulingDelayMs = 1;
11 } // namespace
13 FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment,
14 CastTransportSender* const transport_sender,
15 base::TimeDelta rtcp_interval,
16 int rtp_timebase,
17 uint32 ssrc,
18 double max_frame_rate,
19 base::TimeDelta playout_delay)
20 : cast_environment_(cast_environment),
21 transport_sender_(transport_sender),
22 ssrc_(ssrc),
23 rtt_available_(false),
24 rtcp_interval_(rtcp_interval),
25 max_frame_rate_(max_frame_rate),
26 num_aggressive_rtcp_reports_sent_(0),
27 last_sent_frame_id_(0),
28 latest_acked_frame_id_(0),
29 duplicate_ack_counter_(0),
30 rtp_timebase_(rtp_timebase),
31 weak_factory_(this) {
32 DCHECK_GT(rtp_timebase_, 0);
33 SetTargetPlayoutDelay(playout_delay);
34 send_target_playout_delay_ = false;
35 memset(frame_rtp_timestamps_, 0, sizeof(frame_rtp_timestamps_));
38 FrameSender::~FrameSender() {
41 void FrameSender::ScheduleNextRtcpReport() {
42 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
43 base::TimeDelta time_to_next = rtcp_interval_;
45 time_to_next = std::max(
46 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
48 cast_environment_->PostDelayedTask(
49 CastEnvironment::MAIN,
50 FROM_HERE,
51 base::Bind(&FrameSender::SendRtcpReport, weak_factory_.GetWeakPtr(),
52 true),
53 time_to_next);
56 void FrameSender::SendRtcpReport(bool schedule_future_reports) {
57 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
59 // Sanity-check: We should have sent at least the first frame by this point.
60 DCHECK(!last_send_time_.is_null());
62 // Create lip-sync info for the sender report. The last sent frame's
63 // reference time and RTP timestamp are used to estimate an RTP timestamp in
64 // terms of "now." Note that |now| is never likely to be precise to an exact
65 // frame boundary; and so the computation here will result in a
66 // |now_as_rtp_timestamp| value that is rarely equal to any one emitted by the
67 // encoder.
68 const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
69 const base::TimeDelta time_delta =
70 now - GetRecordedReferenceTime(last_sent_frame_id_);
71 const int64 rtp_delta = TimeDeltaToRtpDelta(time_delta, rtp_timebase_);
72 const uint32 now_as_rtp_timestamp =
73 GetRecordedRtpTimestamp(last_sent_frame_id_) +
74 static_cast<uint32>(rtp_delta);
75 transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp);
77 if (schedule_future_reports)
78 ScheduleNextRtcpReport();
81 void FrameSender::OnReceivedRtt(base::TimeDelta rtt,
82 base::TimeDelta avg_rtt,
83 base::TimeDelta min_rtt,
84 base::TimeDelta max_rtt) {
85 rtt_available_ = true;
86 rtt_ = rtt;
87 avg_rtt_ = avg_rtt;
88 min_rtt_ = min_rtt;
89 max_rtt_ = max_rtt;
92 void FrameSender::SetTargetPlayoutDelay(
93 base::TimeDelta new_target_playout_delay) {
94 target_playout_delay_ = new_target_playout_delay;
95 max_unacked_frames_ =
96 std::min(kMaxUnackedFrames,
97 1 + static_cast<int>(target_playout_delay_ *
98 max_frame_rate_ /
99 base::TimeDelta::FromSeconds(1)));
100 send_target_playout_delay_ = true;
103 void FrameSender::ResendCheck() {
104 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
105 DCHECK(!last_send_time_.is_null());
106 const base::TimeDelta time_since_last_send =
107 cast_environment_->Clock()->NowTicks() - last_send_time_;
108 if (time_since_last_send > target_playout_delay_) {
109 if (latest_acked_frame_id_ == last_sent_frame_id_) {
110 // Last frame acked, no point in doing anything
111 } else {
112 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_;
113 ResendForKickstart();
116 ScheduleNextResendCheck();
119 void FrameSender::ScheduleNextResendCheck() {
120 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
121 DCHECK(!last_send_time_.is_null());
122 base::TimeDelta time_to_next =
123 last_send_time_ - cast_environment_->Clock()->NowTicks() +
124 target_playout_delay_;
125 time_to_next = std::max(
126 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
127 cast_environment_->PostDelayedTask(
128 CastEnvironment::MAIN,
129 FROM_HERE,
130 base::Bind(&FrameSender::ResendCheck, weak_factory_.GetWeakPtr()),
131 time_to_next);
134 void FrameSender::ResendForKickstart() {
135 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
136 DCHECK(!last_send_time_.is_null());
137 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_
138 << " to kick-start.";
139 last_send_time_ = cast_environment_->Clock()->NowTicks();
140 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_);
143 void FrameSender::RecordLatestFrameTimestamps(uint32 frame_id,
144 base::TimeTicks reference_time,
145 RtpTimestamp rtp_timestamp) {
146 DCHECK(!reference_time.is_null());
147 frame_reference_times_[frame_id % arraysize(frame_reference_times_)] =
148 reference_time;
149 frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)] =
150 rtp_timestamp;
153 base::TimeTicks FrameSender::GetRecordedReferenceTime(uint32 frame_id) const {
154 return frame_reference_times_[frame_id % arraysize(frame_reference_times_)];
157 RtpTimestamp FrameSender::GetRecordedRtpTimestamp(uint32 frame_id) const {
158 return frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)];
161 } // namespace cast
162 } // namespace media