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/audio_sender.h" | 5 #include "media/cast/sender/audio_sender.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "media/cast/cast_defines.h" | 10 #include "media/cast/cast_defines.h" |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 | 77 |
78 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus, | 78 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus, |
79 const base::TimeTicks& recorded_time) { | 79 const base::TimeTicks& recorded_time) { |
80 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 80 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
81 if (cast_initialization_status_ != STATUS_AUDIO_INITIALIZED) { | 81 if (cast_initialization_status_ != STATUS_AUDIO_INITIALIZED) { |
82 NOTREACHED(); | 82 NOTREACHED(); |
83 return; | 83 return; |
84 } | 84 } |
85 DCHECK(audio_encoder_.get()) << "Invalid internal state"; | 85 DCHECK(audio_encoder_.get()) << "Invalid internal state"; |
86 | 86 |
87 if (AreTooManyFramesInFlight()) { | 87 if (ShouldDropNextFrame(recorded_time)) { |
88 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; | 88 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; |
89 return; | 89 return; |
90 } | 90 } |
91 | 91 |
92 audio_encoder_->InsertAudio(audio_bus.Pass(), recorded_time); | 92 audio_encoder_->InsertAudio(audio_bus.Pass(), recorded_time); |
93 } | 93 } |
94 | 94 |
95 void AudioSender::SendEncodedAudioFrame( | 95 void AudioSender::SendEncodedAudioFrame( |
96 scoped_ptr<EncodedFrame> encoded_frame) { | 96 scoped_ptr<EncodedFrame> encoded_frame) { |
97 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 97 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
98 | 98 |
99 const uint32 frame_id = encoded_frame->frame_id; | 99 const uint32 frame_id = encoded_frame->frame_id; |
100 | 100 |
101 const bool is_first_frame_to_be_sent = last_send_time_.is_null(); | 101 const bool is_first_frame_to_be_sent = last_send_time_.is_null(); |
102 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 102 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
103 last_sent_frame_id_ = frame_id; | 103 last_sent_frame_id_ = frame_id; |
104 // If this is the first frame about to be sent, fake the value of | 104 // If this is the first frame about to be sent, fake the value of |
105 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up. | 105 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up. |
106 // Also, schedule the periodic frame re-send checks. | 106 // Also, schedule the periodic frame re-send checks. |
107 if (is_first_frame_to_be_sent) { | 107 if (is_first_frame_to_be_sent) { |
108 latest_acked_frame_id_ = frame_id - 1; | 108 latest_acked_frame_id_ = frame_id - 1; |
109 ScheduleNextResendCheck(); | 109 ScheduleNextResendCheck(); |
110 } | 110 } |
111 | 111 |
112 cast_environment_->Logging()->InsertEncodedFrameEvent( | 112 cast_environment_->Logging()->InsertEncodedFrameEvent( |
113 last_send_time_, FRAME_ENCODED, AUDIO_EVENT, encoded_frame->rtp_timestamp, | 113 last_send_time_, FRAME_ENCODED, AUDIO_EVENT, encoded_frame->rtp_timestamp, |
114 frame_id, static_cast<int>(encoded_frame->data.size()), | 114 frame_id, static_cast<int>(encoded_frame->data.size()), |
115 encoded_frame->dependency == EncodedFrame::KEY, | 115 encoded_frame->dependency == EncodedFrame::KEY, |
116 configured_encoder_bitrate_); | 116 configured_encoder_bitrate_); |
117 // Only use lowest 8 bits as key. | |
118 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; | |
119 | 117 |
120 DCHECK(!encoded_frame->reference_time.is_null()); | 118 RecordLatestFrameTimestamps(frame_id, |
121 rtp_timestamp_helper_.StoreLatestTime(encoded_frame->reference_time, | 119 encoded_frame->reference_time, |
122 encoded_frame->rtp_timestamp); | 120 encoded_frame->rtp_timestamp); |
123 | 121 |
124 // At the start of the session, it's important to send reports before each | 122 // At the start of the session, it's important to send reports before each |
125 // frame so that the receiver can properly compute playout times. The reason | 123 // frame so that the receiver can properly compute playout times. The reason |
126 // more than one report is sent is because transmission is not guaranteed, | 124 // more than one report is sent is because transmission is not guaranteed, |
127 // only best effort, so we send enough that one should almost certainly get | 125 // only best effort, so we send enough that one should almost certainly get |
128 // through. | 126 // through. |
129 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 127 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
130 // SendRtcpReport() will schedule future reports to be made if this is the | 128 // SendRtcpReport() will schedule future reports to be made if this is the |
131 // last "aggressive report." | 129 // last "aggressive report." |
132 ++num_aggressive_rtcp_reports_sent_; | 130 ++num_aggressive_rtcp_reports_sent_; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { | 171 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { |
174 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; | 172 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; |
175 ResendForKickstart(); | 173 ResendForKickstart(); |
176 } | 174 } |
177 } else { | 175 } else { |
178 // Only count duplicated ACKs if there is no NACK request in between. | 176 // Only count duplicated ACKs if there is no NACK request in between. |
179 // This is to avoid aggresive resend. | 177 // This is to avoid aggresive resend. |
180 duplicate_ack_counter_ = 0; | 178 duplicate_ack_counter_ = 0; |
181 } | 179 } |
182 | 180 |
183 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 181 cast_environment_->Logging()->InsertFrameEvent( |
184 | 182 cast_environment_->Clock()->NowTicks(), |
185 const RtpTimestamp rtp_timestamp = | 183 FRAME_ACK_RECEIVED, |
186 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff]; | 184 AUDIO_EVENT, |
187 cast_environment_->Logging()->InsertFrameEvent(now, | 185 GetRecordedRtpTimestamp(cast_feedback.ack_frame_id), |
188 FRAME_ACK_RECEIVED, | 186 cast_feedback.ack_frame_id); |
189 AUDIO_EVENT, | |
190 rtp_timestamp, | |
191 cast_feedback.ack_frame_id); | |
192 | 187 |
193 const bool is_acked_out_of_order = | 188 const bool is_acked_out_of_order = |
194 static_cast<int32>(cast_feedback.ack_frame_id - | 189 static_cast<int32>(cast_feedback.ack_frame_id - |
195 latest_acked_frame_id_) < 0; | 190 latest_acked_frame_id_) < 0; |
196 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") | 191 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") |
197 << " for frame " << cast_feedback.ack_frame_id; | 192 << " for frame " << cast_feedback.ack_frame_id; |
198 if (!is_acked_out_of_order) { | 193 if (!is_acked_out_of_order) { |
199 // Cancel resends of acked frames. | 194 // Cancel resends of acked frames. |
200 std::vector<uint32> cancel_sending_frames; | 195 std::vector<uint32> cancel_sending_frames; |
201 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { | 196 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { |
202 latest_acked_frame_id_++; | 197 latest_acked_frame_id_++; |
203 cancel_sending_frames.push_back(latest_acked_frame_id_); | 198 cancel_sending_frames.push_back(latest_acked_frame_id_); |
204 } | 199 } |
205 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); | 200 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
206 latest_acked_frame_id_ = cast_feedback.ack_frame_id; | 201 latest_acked_frame_id_ = cast_feedback.ack_frame_id; |
207 } | 202 } |
208 } | 203 } |
209 | 204 |
210 bool AudioSender::AreTooManyFramesInFlight() const { | 205 bool AudioSender::ShouldDropNextFrame(base::TimeTicks capture_time) const { |
211 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 206 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
212 int frames_in_flight = 0; | 207 int frames_in_flight = 0; |
| 208 base::TimeDelta duration_in_flight; |
213 if (!last_send_time_.is_null()) { | 209 if (!last_send_time_.is_null()) { |
214 frames_in_flight += | 210 frames_in_flight = |
215 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); | 211 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); |
| 212 if (frames_in_flight > 0) { |
| 213 const uint32 oldest_unacked_frame_id = latest_acked_frame_id_ + 1; |
| 214 duration_in_flight = |
| 215 capture_time - GetRecordedReferenceTime(oldest_unacked_frame_id); |
| 216 } |
216 } | 217 } |
217 VLOG(2) << frames_in_flight | 218 VLOG(2) << frames_in_flight |
218 << " frames in flight; last sent: " << last_sent_frame_id_ | 219 << " frames in flight; last sent: " << last_sent_frame_id_ |
219 << " latest acked: " << latest_acked_frame_id_; | 220 << "; latest acked: " << latest_acked_frame_id_ |
220 return frames_in_flight >= max_unacked_frames_; | 221 << "; duration in flight: " |
| 222 << duration_in_flight.InMicroseconds() << " usec (" |
| 223 << (target_playout_delay_ > base::TimeDelta() ? |
| 224 100 * duration_in_flight / target_playout_delay_ : |
| 225 kint64max) << "%)"; |
| 226 return frames_in_flight >= max_unacked_frames_ || |
| 227 duration_in_flight >= target_playout_delay_; |
221 } | 228 } |
222 | 229 |
223 } // namespace cast | 230 } // namespace cast |
224 } // namespace media | 231 } // namespace media |
OLD | NEW |