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/frame_sender.h" | 5 #include "media/cast/sender/frame_sender.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 animated_playout_delay_(animated_playout_delay == base::TimeDelta() | 52 animated_playout_delay_(animated_playout_delay == base::TimeDelta() |
53 ? max_playout_delay | 53 ? max_playout_delay |
54 : animated_playout_delay), | 54 : animated_playout_delay), |
55 send_target_playout_delay_(false), | 55 send_target_playout_delay_(false), |
56 max_frame_rate_(max_frame_rate), | 56 max_frame_rate_(max_frame_rate), |
57 num_aggressive_rtcp_reports_sent_(0), | 57 num_aggressive_rtcp_reports_sent_(0), |
58 last_sent_frame_id_(0), | 58 last_sent_frame_id_(0), |
59 latest_acked_frame_id_(0), | 59 latest_acked_frame_id_(0), |
60 duplicate_ack_counter_(0), | 60 duplicate_ack_counter_(0), |
61 congestion_control_(congestion_control), | 61 congestion_control_(congestion_control), |
| 62 picture_lost_at_receiver_(false), |
62 rtp_timebase_(rtp_timebase), | 63 rtp_timebase_(rtp_timebase), |
63 is_audio_(is_audio), | 64 is_audio_(is_audio), |
64 weak_factory_(this) { | 65 weak_factory_(this) { |
65 DCHECK(transport_sender_); | 66 DCHECK(transport_sender_); |
66 DCHECK_GT(rtp_timebase_, 0); | 67 DCHECK_GT(rtp_timebase_, 0); |
67 DCHECK(congestion_control_); | 68 DCHECK(congestion_control_); |
68 // We assume animated content to begin with since that is the common use | 69 // We assume animated content to begin with since that is the common use |
69 // case today. | 70 // case today. |
70 VLOG(1) << SENDER_SSRC << "min latency " | 71 VLOG(1) << SENDER_SSRC << "min latency " |
71 << min_playout_delay_.InMilliseconds() << "max latency " | 72 << min_playout_delay_.InMilliseconds() << "max latency " |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 | 213 |
213 void FrameSender::SendEncodedFrame( | 214 void FrameSender::SendEncodedFrame( |
214 int requested_bitrate_before_encode, | 215 int requested_bitrate_before_encode, |
215 scoped_ptr<SenderEncodedFrame> encoded_frame) { | 216 scoped_ptr<SenderEncodedFrame> encoded_frame) { |
216 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 217 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
217 | 218 |
218 VLOG(2) << SENDER_SSRC << "About to send another frame: last_sent=" | 219 VLOG(2) << SENDER_SSRC << "About to send another frame: last_sent=" |
219 << last_sent_frame_id_ << ", latest_acked=" << latest_acked_frame_id_; | 220 << last_sent_frame_id_ << ", latest_acked=" << latest_acked_frame_id_; |
220 | 221 |
221 const uint32_t frame_id = encoded_frame->frame_id; | 222 const uint32_t frame_id = encoded_frame->frame_id; |
| 223 const bool is_first_frame_to_be_sent = last_send_time_.is_null(); |
222 | 224 |
223 const bool is_first_frame_to_be_sent = last_send_time_.is_null(); | 225 if (picture_lost_at_receiver_ && |
| 226 (encoded_frame->dependency == EncodedFrame::KEY)) { |
| 227 picture_lost_at_receiver_ = false; |
| 228 DCHECK(frame_id > latest_acked_frame_id_); |
| 229 // Cancel sending remaining frames. |
| 230 std::vector<uint32_t> cancel_sending_frames; |
| 231 for (uint32_t id = latest_acked_frame_id_ + 1; id < frame_id; ++id) { |
| 232 cancel_sending_frames.push_back(id); |
| 233 } |
| 234 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
| 235 } |
| 236 |
224 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 237 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
225 last_sent_frame_id_ = frame_id; | 238 last_sent_frame_id_ = frame_id; |
226 // If this is the first frame about to be sent, fake the value of | 239 // If this is the first frame about to be sent, fake the value of |
227 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up. | 240 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up. |
228 // Also, schedule the periodic frame re-send checks. | 241 // Also, schedule the periodic frame re-send checks. |
229 if (is_first_frame_to_be_sent) { | 242 if (is_first_frame_to_be_sent) { |
230 latest_acked_frame_id_ = frame_id - 1; | 243 latest_acked_frame_id_ = frame_id - 1; |
231 ScheduleNextResendCheck(); | 244 ScheduleNextResendCheck(); |
232 } | 245 } |
233 | 246 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 TRACE_EVENT_ASYNC_END1("cast.stream", | 393 TRACE_EVENT_ASYNC_END1("cast.stream", |
381 is_audio_ ? "Audio Transport" : "Video Transport", | 394 is_audio_ ? "Audio Transport" : "Video Transport", |
382 cast_feedback.ack_frame_id, | 395 cast_feedback.ack_frame_id, |
383 "RTT_usecs", current_round_trip_time_.InMicroseconds()); | 396 "RTT_usecs", current_round_trip_time_.InMicroseconds()); |
384 } | 397 } |
385 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); | 398 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
386 latest_acked_frame_id_ = cast_feedback.ack_frame_id; | 399 latest_acked_frame_id_ = cast_feedback.ack_frame_id; |
387 } | 400 } |
388 } | 401 } |
389 | 402 |
| 403 void FrameSender::OnReceivedPli() { |
| 404 picture_lost_at_receiver_ = true; |
| 405 } |
| 406 |
390 bool FrameSender::ShouldDropNextFrame(base::TimeDelta frame_duration) const { | 407 bool FrameSender::ShouldDropNextFrame(base::TimeDelta frame_duration) const { |
391 // Check that accepting the next frame won't cause more frames to become | 408 // Check that accepting the next frame won't cause more frames to become |
392 // in-flight than the system's design limit. | 409 // in-flight than the system's design limit. |
393 const int count_frames_in_flight = | 410 const int count_frames_in_flight = |
394 GetUnacknowledgedFrameCount() + GetNumberOfFramesInEncoder(); | 411 GetUnacknowledgedFrameCount() + GetNumberOfFramesInEncoder(); |
395 if (count_frames_in_flight >= kMaxUnackedFrames) { | 412 if (count_frames_in_flight >= kMaxUnackedFrames) { |
396 VLOG(1) << SENDER_SSRC << "Dropping: Too many frames would be in-flight."; | 413 VLOG(1) << SENDER_SSRC << "Dropping: Too many frames would be in-flight."; |
397 return true; | 414 return true; |
398 } | 415 } |
399 | 416 |
(...skipping 27 matching lines...) Expand all Loading... |
427 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; | 444 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; |
428 return true; | 445 return true; |
429 } | 446 } |
430 | 447 |
431 // Next frame is accepted. | 448 // Next frame is accepted. |
432 return false; | 449 return false; |
433 } | 450 } |
434 | 451 |
435 } // namespace cast | 452 } // namespace cast |
436 } // namespace media | 453 } // namespace media |
OLD | NEW |