OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/video_sender/video_sender.h" | 5 #include "media/cast/video_sender/video_sender.h" |
6 | 6 |
7 #include <cstring> | 7 #include <cstring> |
8 #include <list> | 8 #include <list> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 transport_sender_(transport_sender), | 58 transport_sender_(transport_sender), |
59 event_subscriber_(kMaxEventSubscriberEntries), | 59 event_subscriber_(kMaxEventSubscriberEntries), |
60 rtp_stats_(kVideoFrequency), | 60 rtp_stats_(kVideoFrequency), |
61 rtcp_feedback_(new LocalRtcpVideoSenderFeedback(this)), | 61 rtcp_feedback_(new LocalRtcpVideoSenderFeedback(this)), |
62 last_acked_frame_id_(-1), | 62 last_acked_frame_id_(-1), |
63 last_sent_frame_id_(-1), | 63 last_sent_frame_id_(-1), |
64 frames_in_encoder_(0), | 64 frames_in_encoder_(0), |
65 duplicate_ack_(0), | 65 duplicate_ack_(0), |
66 last_skip_count_(0), | 66 last_skip_count_(0), |
67 current_requested_bitrate_(video_config.start_bitrate), | 67 current_requested_bitrate_(video_config.start_bitrate), |
| 68 current_bitrate_divider_(1), |
68 congestion_control_(cast_environment->Clock(), | 69 congestion_control_(cast_environment->Clock(), |
69 video_config.congestion_control_back_off, | 70 video_config.congestion_control_back_off, |
70 video_config.max_bitrate, | 71 video_config.max_bitrate, |
71 video_config.min_bitrate, | 72 video_config.min_bitrate, |
72 video_config.start_bitrate), | 73 video_config.start_bitrate), |
73 initialized_(false), | 74 initialized_(false), |
74 active_session_(false), | 75 active_session_(false), |
75 weak_factory_(this) { | 76 weak_factory_(this) { |
76 max_unacked_frames_ = | 77 max_unacked_frames_ = |
77 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms * | 78 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms * |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 VLOG(1) << "Send encoded key frame; frame_id:" | 178 VLOG(1) << "Send encoded key frame; frame_id:" |
178 << static_cast<int>(encoded_frame->frame_id); | 179 << static_cast<int>(encoded_frame->frame_id); |
179 } | 180 } |
180 | 181 |
181 DCHECK_GT(frames_in_encoder_, 0); | 182 DCHECK_GT(frames_in_encoder_, 0); |
182 frames_in_encoder_--; | 183 frames_in_encoder_--; |
183 uint32 frame_id = encoded_frame->frame_id; | 184 uint32 frame_id = encoded_frame->frame_id; |
184 cast_environment_->Logging()->InsertEncodedFrameEvent( | 185 cast_environment_->Logging()->InsertEncodedFrameEvent( |
185 last_send_time_, kVideoFrameEncoded, encoded_frame->rtp_timestamp, | 186 last_send_time_, kVideoFrameEncoded, encoded_frame->rtp_timestamp, |
186 frame_id, static_cast<int>(encoded_frame->data.size()), | 187 frame_id, static_cast<int>(encoded_frame->data.size()), |
187 encoded_frame->key_frame, current_requested_bitrate_); | 188 encoded_frame->key_frame, |
| 189 current_requested_bitrate_); |
188 | 190 |
189 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 191 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
190 TRACE_EVENT_INSTANT1( | 192 TRACE_EVENT_INSTANT1( |
191 "cast_perf_test", "VideoFrameEncoded", | 193 "cast_perf_test", "VideoFrameEncoded", |
192 TRACE_EVENT_SCOPE_THREAD, | 194 TRACE_EVENT_SCOPE_THREAD, |
193 "rtp_timestamp", GetVideoRtpTimestamp(capture_time)); | 195 "rtp_timestamp", GetVideoRtpTimestamp(capture_time)); |
194 | 196 |
195 // Only use lowest 8 bits as key. | 197 // Only use lowest 8 bits as key. |
196 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; | 198 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; |
197 | 199 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 int resend_frame = -1; | 382 int resend_frame = -1; |
381 if (last_sent_frame_id_ == -1) | 383 if (last_sent_frame_id_ == -1) |
382 return; | 384 return; |
383 | 385 |
384 video_encoder_->LatestFrameIdToReference(cast_feedback.ack_frame_id_); | 386 video_encoder_->LatestFrameIdToReference(cast_feedback.ack_frame_id_); |
385 | 387 |
386 if (static_cast<uint32>(last_acked_frame_id_ + 1) == | 388 if (static_cast<uint32>(last_acked_frame_id_ + 1) == |
387 cast_feedback.ack_frame_id_) { | 389 cast_feedback.ack_frame_id_) { |
388 uint32 new_bitrate = 0; | 390 uint32 new_bitrate = 0; |
389 if (congestion_control_.OnAck(rtt, &new_bitrate)) { | 391 if (congestion_control_.OnAck(rtt, &new_bitrate)) { |
390 video_encoder_->SetBitRate(new_bitrate); | 392 UpdateBitrate(new_bitrate); |
391 current_requested_bitrate_ = new_bitrate; | |
392 } | 393 } |
393 } | 394 } |
394 // We only count duplicate ACKs when we have sent newer frames. | 395 // We only count duplicate ACKs when we have sent newer frames. |
395 if (static_cast<uint32>(last_acked_frame_id_) == | 396 if (static_cast<uint32>(last_acked_frame_id_) == |
396 cast_feedback.ack_frame_id_ && | 397 cast_feedback.ack_frame_id_ && |
397 IsNewerFrameId(last_sent_frame_id_, last_acked_frame_id_)) { | 398 IsNewerFrameId(last_sent_frame_id_, last_acked_frame_id_)) { |
398 duplicate_ack_++; | 399 duplicate_ack_++; |
399 } else { | 400 } else { |
400 duplicate_ack_ = 0; | 401 duplicate_ack_ = 0; |
401 } | 402 } |
402 if (duplicate_ack_ >= 2 && duplicate_ack_ % 3 == 2) { | 403 if (duplicate_ack_ >= 2 && duplicate_ack_ % 3 == 2) { |
403 // Resend last ACK + 1 frame. | 404 // Resend last ACK + 1 frame. |
404 resend_frame = static_cast<uint32>(last_acked_frame_id_ + 1); | 405 resend_frame = static_cast<uint32>(last_acked_frame_id_ + 1); |
405 } | 406 } |
406 if (resend_frame != -1) { | 407 if (resend_frame != -1) { |
407 DCHECK_LE(0, resend_frame); | 408 DCHECK_LE(0, resend_frame); |
408 VLOG(1) << "Received duplicate ACK for frame:" | 409 VLOG(1) << "Received duplicate ACK for frame:" |
409 << static_cast<int>(resend_frame); | 410 << static_cast<int>(resend_frame); |
410 ResendFrame(static_cast<uint32>(resend_frame)); | 411 ResendFrame(static_cast<uint32>(resend_frame)); |
411 } | 412 } |
412 } else { | 413 } else { |
413 transport_sender_->ResendPackets( | 414 transport_sender_->ResendPackets( |
414 false, cast_feedback.missing_frames_and_packets_); | 415 false, cast_feedback.missing_frames_and_packets_); |
415 uint32 new_bitrate = 0; | 416 uint32 new_bitrate = 0; |
416 if (congestion_control_.OnNack(rtt, &new_bitrate)) { | 417 if (congestion_control_.OnNack(rtt, &new_bitrate)) { |
417 video_encoder_->SetBitRate(new_bitrate); | 418 UpdateBitrate(new_bitrate); |
418 current_requested_bitrate_ = new_bitrate; | |
419 } | 419 } |
420 } | 420 } |
421 ReceivedAck(cast_feedback.ack_frame_id_); | 421 ReceivedAck(cast_feedback.ack_frame_id_); |
422 } | 422 } |
423 | 423 |
424 void VideoSender::ReceivedAck(uint32 acked_frame_id) { | 424 void VideoSender::ReceivedAck(uint32 acked_frame_id) { |
425 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 425 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
426 if (acked_frame_id == UINT32_C(0xFFFFFFFF)) { | 426 if (acked_frame_id == UINT32_C(0xFFFFFFFF)) { |
427 // Receiver is sending a status message before any frames are ready to | 427 // Receiver is sending a status message before any frames are ready to |
428 // be acked. Ignore. | 428 // be acked. Ignore. |
(...skipping 15 matching lines...) Expand all Loading... |
444 VLOG(2) << "ReceivedAck:" << static_cast<int>(acked_frame_id); | 444 VLOG(2) << "ReceivedAck:" << static_cast<int>(acked_frame_id); |
445 active_session_ = true; | 445 active_session_ = true; |
446 DCHECK_NE(-1, last_acked_frame_id_); | 446 DCHECK_NE(-1, last_acked_frame_id_); |
447 UpdateFramesInFlight(); | 447 UpdateFramesInFlight(); |
448 } | 448 } |
449 | 449 |
450 void VideoSender::UpdateFramesInFlight() { | 450 void VideoSender::UpdateFramesInFlight() { |
451 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 451 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
452 if (last_sent_frame_id_ != -1) { | 452 if (last_sent_frame_id_ != -1) { |
453 DCHECK_LE(0, last_sent_frame_id_); | 453 DCHECK_LE(0, last_sent_frame_id_); |
454 uint32 frames_in_flight = 0; | 454 int frames_in_flight = 0; |
455 if (last_acked_frame_id_ != -1) { | 455 if (last_acked_frame_id_ != -1) { |
456 DCHECK_LE(0, last_acked_frame_id_); | 456 DCHECK_LE(0, last_acked_frame_id_); |
457 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) - | 457 frames_in_flight = last_sent_frame_id_ - last_acked_frame_id_; |
458 static_cast<uint32>(last_acked_frame_id_); | |
459 } else { | 458 } else { |
460 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; | 459 frames_in_flight = last_sent_frame_id_ + 1; |
461 } | 460 } |
462 frames_in_flight += frames_in_encoder_; | 461 frames_in_flight += frames_in_encoder_; |
463 VLOG(2) << frames_in_flight | 462 VLOG(2) << frames_in_flight |
464 << " Frames in flight; last sent: " << last_sent_frame_id_ | 463 << " Frames in flight; last sent: " << last_sent_frame_id_ |
465 << " last acked:" << last_acked_frame_id_ | 464 << " last acked:" << last_acked_frame_id_ |
466 << " frames in encoder: " << frames_in_encoder_; | 465 << " frames in encoder: " << frames_in_encoder_; |
467 if (frames_in_flight >= max_unacked_frames_) { | 466 if (frames_in_flight >= max_unacked_frames_) { |
468 video_encoder_->SkipNextFrame(true); | 467 video_encoder_->SkipNextFrame(true); |
469 return; | 468 return; |
| 469 } else if (frames_in_flight > max_unacked_frames_ * 4 / 5) { |
| 470 current_bitrate_divider_ = 3; |
| 471 } else if (frames_in_flight > max_unacked_frames_ * 2 / 3) { |
| 472 current_bitrate_divider_ = 2; |
| 473 } else { |
| 474 current_bitrate_divider_ = 1; |
470 } | 475 } |
471 DCHECK(frames_in_flight <= max_unacked_frames_); | 476 DCHECK(frames_in_flight <= max_unacked_frames_); |
472 } | 477 } |
473 video_encoder_->SkipNextFrame(false); | 478 video_encoder_->SkipNextFrame(false); |
474 } | 479 } |
475 | 480 |
476 void VideoSender::ResendFrame(uint32 resend_frame_id) { | 481 void VideoSender::ResendFrame(uint32 resend_frame_id) { |
477 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 482 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
478 MissingFramesAndPacketsMap missing_frames_and_packets; | 483 MissingFramesAndPacketsMap missing_frames_and_packets; |
479 PacketIdSet missing; | 484 PacketIdSet missing; |
480 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); | 485 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); |
481 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 486 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
482 transport_sender_->ResendPackets(false, missing_frames_and_packets); | 487 transport_sender_->ResendPackets(false, missing_frames_and_packets); |
483 } | 488 } |
484 | 489 |
| 490 void VideoSender::UpdateBitrate(int new_bitrate) { |
| 491 new_bitrate /= current_bitrate_divider_; |
| 492 // Make sure we don't set the bitrate too insanely low. |
| 493 DCHECK_GT(new_bitrate, 1000); |
| 494 video_encoder_->SetBitRate(new_bitrate); |
| 495 current_requested_bitrate_ = new_bitrate; |
| 496 } |
| 497 |
485 } // namespace cast | 498 } // namespace cast |
486 } // namespace media | 499 } // namespace media |
OLD | NEW |