Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: media/cast/sender/audio_sender.cc

Issue 502333002: [Cast] In Audio/VideoSender, drop frames when too-long a duration is in-flight. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix missing brace (rebase oops). Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/cast/sender/audio_sender.h ('k') | media/cast/sender/frame_sender.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « media/cast/sender/audio_sender.h ('k') | media/cast/sender/frame_sender.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698