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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 TRACE_EVENT_ASYNC_END1("cast.stream", | 387 TRACE_EVENT_ASYNC_END1("cast.stream", |
375 is_audio_ ? "Audio Transport" : "Video Transport", | 388 is_audio_ ? "Audio Transport" : "Video Transport", |
376 cast_feedback.ack_frame_id, | 389 cast_feedback.ack_frame_id, |
377 "RTT_usecs", current_round_trip_time_.InMicroseconds()); | 390 "RTT_usecs", current_round_trip_time_.InMicroseconds()); |
378 } | 391 } |
379 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); | 392 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
380 latest_acked_frame_id_ = cast_feedback.ack_frame_id; | 393 latest_acked_frame_id_ = cast_feedback.ack_frame_id; |
381 } | 394 } |
382 } | 395 } |
383 | 396 |
| 397 void FrameSender::OnReceivedPli() { |
| 398 picture_lost_at_receiver_ = true; |
| 399 } |
| 400 |
384 bool FrameSender::ShouldDropNextFrame(base::TimeDelta frame_duration) const { | 401 bool FrameSender::ShouldDropNextFrame(base::TimeDelta frame_duration) const { |
385 // Check that accepting the next frame won't cause more frames to become | 402 // Check that accepting the next frame won't cause more frames to become |
386 // in-flight than the system's design limit. | 403 // in-flight than the system's design limit. |
387 const int count_frames_in_flight = | 404 const int count_frames_in_flight = |
388 GetUnacknowledgedFrameCount() + GetNumberOfFramesInEncoder(); | 405 GetUnacknowledgedFrameCount() + GetNumberOfFramesInEncoder(); |
389 if (count_frames_in_flight >= kMaxUnackedFrames) { | 406 if (count_frames_in_flight >= kMaxUnackedFrames) { |
390 VLOG(1) << SENDER_SSRC << "Dropping: Too many frames would be in-flight."; | 407 VLOG(1) << SENDER_SSRC << "Dropping: Too many frames would be in-flight."; |
391 return true; | 408 return true; |
392 } | 409 } |
393 | 410 |
(...skipping 27 matching lines...) Expand all Loading... |
421 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; | 438 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high."; |
422 return true; | 439 return true; |
423 } | 440 } |
424 | 441 |
425 // Next frame is accepted. | 442 // Next frame is accepted. |
426 return false; | 443 return false; |
427 } | 444 } |
428 | 445 |
429 } // namespace cast | 446 } // namespace cast |
430 } // namespace media | 447 } // namespace media |
OLD | NEW |