| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 | 83 |
| 84 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus, | 84 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus, |
| 85 const base::TimeTicks& recorded_time) { | 85 const base::TimeTicks& recorded_time) { |
| 86 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 86 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 87 if (cast_initialization_status_ != STATUS_AUDIO_INITIALIZED) { | 87 if (cast_initialization_status_ != STATUS_AUDIO_INITIALIZED) { |
| 88 NOTREACHED(); | 88 NOTREACHED(); |
| 89 return; | 89 return; |
| 90 } | 90 } |
| 91 DCHECK(audio_encoder_.get()) << "Invalid internal state"; | 91 DCHECK(audio_encoder_.get()) << "Invalid internal state"; |
| 92 | 92 |
| 93 if (AreTooManyFramesInFlight()) { | 93 if (ShouldDropNextFrame(recorded_time)) { |
| 94 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; | 94 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; |
| 95 return; | 95 return; |
| 96 } | 96 } |
| 97 | 97 |
| 98 audio_encoder_->InsertAudio(audio_bus.Pass(), recorded_time); | 98 audio_encoder_->InsertAudio(audio_bus.Pass(), recorded_time); |
| 99 } | 99 } |
| 100 | 100 |
| 101 void AudioSender::SendEncodedAudioFrame( | 101 void AudioSender::SendEncodedAudioFrame( |
| 102 scoped_ptr<EncodedFrame> encoded_frame) { | 102 scoped_ptr<EncodedFrame> encoded_frame) { |
| 103 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 103 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 104 | 104 |
| 105 const uint32 frame_id = encoded_frame->frame_id; | 105 const uint32 frame_id = encoded_frame->frame_id; |
| 106 | 106 |
| 107 const bool is_first_frame_to_be_sent = last_send_time_.is_null(); | 107 const bool is_first_frame_to_be_sent = last_send_time_.is_null(); |
| 108 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 108 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 109 last_sent_frame_id_ = frame_id; | 109 last_sent_frame_id_ = frame_id; |
| 110 // If this is the first frame about to be sent, fake the value of | 110 // If this is the first frame about to be sent, fake the value of |
| 111 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up. | 111 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up. |
| 112 // Also, schedule the periodic frame re-send checks. | 112 // Also, schedule the periodic frame re-send checks. |
| 113 if (is_first_frame_to_be_sent) { | 113 if (is_first_frame_to_be_sent) { |
| 114 latest_acked_frame_id_ = frame_id - 1; | 114 latest_acked_frame_id_ = frame_id - 1; |
| 115 frame_id_to_rtp_timestamp_[latest_acked_frame_id_ & 0xff] = |
| 116 encoded_frame->rtp_timestamp; |
| 115 ScheduleNextResendCheck(); | 117 ScheduleNextResendCheck(); |
| 116 } | 118 } |
| 117 | 119 |
| 118 cast_environment_->Logging()->InsertEncodedFrameEvent( | 120 cast_environment_->Logging()->InsertEncodedFrameEvent( |
| 119 last_send_time_, FRAME_ENCODED, AUDIO_EVENT, encoded_frame->rtp_timestamp, | 121 last_send_time_, FRAME_ENCODED, AUDIO_EVENT, encoded_frame->rtp_timestamp, |
| 120 frame_id, static_cast<int>(encoded_frame->data.size()), | 122 frame_id, static_cast<int>(encoded_frame->data.size()), |
| 121 encoded_frame->dependency == EncodedFrame::KEY, | 123 encoded_frame->dependency == EncodedFrame::KEY, |
| 122 configured_encoder_bitrate_); | 124 configured_encoder_bitrate_); |
| 123 // Only use lowest 8 bits as key. | 125 // Only use lowest 8 bits as key. |
| 124 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; | 126 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 std::vector<uint32> cancel_sending_frames; | 239 std::vector<uint32> cancel_sending_frames; |
| 238 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { | 240 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { |
| 239 latest_acked_frame_id_++; | 241 latest_acked_frame_id_++; |
| 240 cancel_sending_frames.push_back(latest_acked_frame_id_); | 242 cancel_sending_frames.push_back(latest_acked_frame_id_); |
| 241 } | 243 } |
| 242 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); | 244 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
| 243 latest_acked_frame_id_ = cast_feedback.ack_frame_id; | 245 latest_acked_frame_id_ = cast_feedback.ack_frame_id; |
| 244 } | 246 } |
| 245 } | 247 } |
| 246 | 248 |
| 247 bool AudioSender::AreTooManyFramesInFlight() const { | 249 bool AudioSender::ShouldDropNextFrame(base::TimeTicks capture_time) const { |
| 248 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 250 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 249 int frames_in_flight = 0; | 251 int frames_in_flight = 0; |
| 252 int32 rtp_duration_in_flight = 0; |
| 250 if (!last_send_time_.is_null()) { | 253 if (!last_send_time_.is_null()) { |
| 251 frames_in_flight += | 254 frames_in_flight = |
| 252 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); | 255 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); |
| 256 uint32 estimated_rtp_timestamp; |
| 257 if (frames_in_flight > 0 && |
| 258 rtp_timestamp_helper_.EstimateRtpTimestamp(capture_time, |
| 259 &estimated_rtp_timestamp)) { |
| 260 const uint32 oldest_unacked_frame_id = latest_acked_frame_id_ + 1; |
| 261 rtp_duration_in_flight = static_cast<int32>( |
| 262 estimated_rtp_timestamp - |
| 263 frame_id_to_rtp_timestamp_[oldest_unacked_frame_id & 0xff]); |
| 264 } |
| 253 } | 265 } |
| 254 VLOG(2) << frames_in_flight | 266 VLOG(2) << frames_in_flight |
| 255 << " frames in flight; last sent: " << last_sent_frame_id_ | 267 << " frames in flight; last sent: " << last_sent_frame_id_ |
| 256 << " latest acked: " << latest_acked_frame_id_; | 268 << "; latest acked: " << latest_acked_frame_id_ |
| 257 return frames_in_flight >= max_unacked_frames_; | 269 << "; duration in flight: " |
| 270 << (max_unacked_rtp_delta_ > 0 ? |
| 271 100 * rtp_duration_in_flight / max_unacked_rtp_delta_ : |
| 272 kint32max) << "%"; |
| 273 return frames_in_flight >= max_unacked_frames_ || |
| 274 rtp_duration_in_flight >= max_unacked_rtp_delta_; |
| 258 } | 275 } |
| 259 | 276 |
| 260 void AudioSender::ResendForKickstart() { | 277 void AudioSender::ResendForKickstart() { |
| 261 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 278 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 262 DCHECK(!last_send_time_.is_null()); | 279 DCHECK(!last_send_time_.is_null()); |
| 263 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ | 280 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ |
| 264 << " to kick-start."; | 281 << " to kick-start."; |
| 265 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 282 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 266 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); | 283 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); |
| 267 } | 284 } |
| 268 | 285 |
| 269 } // namespace cast | 286 } // namespace cast |
| 270 } // namespace media | 287 } // namespace media |
| OLD | NEW |