Chromium Code Reviews| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; | 460 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; |
| 461 } | 461 } |
| 462 frames_in_flight += frames_in_encoder_; | 462 frames_in_flight += frames_in_encoder_; |
| 463 VLOG(2) << frames_in_flight | 463 VLOG(2) << frames_in_flight |
| 464 << " Frames in flight; last sent: " << last_sent_frame_id_ | 464 << " Frames in flight; last sent: " << last_sent_frame_id_ |
| 465 << " last acked:" << last_acked_frame_id_ | 465 << " last acked:" << last_acked_frame_id_ |
| 466 << " frames in encoder: " << frames_in_encoder_; | 466 << " frames in encoder: " << frames_in_encoder_; |
| 467 if (frames_in_flight >= max_unacked_frames_) { | 467 if (frames_in_flight >= max_unacked_frames_) { |
| 468 video_encoder_->SkipNextFrame(true); | 468 video_encoder_->SkipNextFrame(true); |
| 469 return; | 469 return; |
| 470 } else if (frames_in_flight > max_unacked_frames_ * 4 / 5) { | |
|
Alpha Left Google
2014/05/09 05:19:03
Looks like this gets a compiler warning turned int
hubbe
2014/05/09 06:56:34
away away away away
| |
| 471 current_bitrate_divider_ = 3; | |
| 472 } else if (frames_in_flight > max_unacked_frames_ * 2 / 3) { | |
| 473 current_bitrate_divider_ = 2; | |
| 474 } else { | |
| 475 current_bitrate_divider_ = 1; | |
| 470 } | 476 } |
| 471 DCHECK(frames_in_flight <= max_unacked_frames_); | 477 DCHECK(frames_in_flight <= max_unacked_frames_); |
| 472 } | 478 } |
| 473 video_encoder_->SkipNextFrame(false); | 479 video_encoder_->SkipNextFrame(false); |
| 474 } | 480 } |
| 475 | 481 |
| 476 void VideoSender::ResendFrame(uint32 resend_frame_id) { | 482 void VideoSender::ResendFrame(uint32 resend_frame_id) { |
| 477 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 483 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 478 MissingFramesAndPacketsMap missing_frames_and_packets; | 484 MissingFramesAndPacketsMap missing_frames_and_packets; |
| 479 PacketIdSet missing; | 485 PacketIdSet missing; |
| 480 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); | 486 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); |
| 481 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 487 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 482 transport_sender_->ResendPackets(false, missing_frames_and_packets); | 488 transport_sender_->ResendPackets(false, missing_frames_and_packets); |
| 483 } | 489 } |
| 484 | 490 |
| 491 void VideoSender::UpdateBitrate(int new_bitrate) { | |
| 492 new_bitrate /= current_bitrate_divider_; | |
| 493 // Make sure we don't set the bitrate too insanely low. | |
| 494 DCHECK_GT(new_bitrate, 1000); | |
| 495 video_encoder_->SetBitRate(new_bitrate); | |
| 496 current_requested_bitrate_ = new_bitrate; | |
| 497 } | |
| 498 | |
| 485 } // namespace cast | 499 } // namespace cast |
| 486 } // namespace media | 500 } // namespace media |
| OLD | NEW |