| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 VideoSender::VideoSender( | 26 VideoSender::VideoSender( |
| 27 scoped_refptr<CastEnvironment> cast_environment, | 27 scoped_refptr<CastEnvironment> cast_environment, |
| 28 const VideoSenderConfig& video_config, | 28 const VideoSenderConfig& video_config, |
| 29 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, | 29 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, |
| 30 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, | 30 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, |
| 31 transport::CastTransportSender* const transport_sender) | 31 transport::CastTransportSender* const transport_sender) |
| 32 : cast_environment_(cast_environment), | 32 : cast_environment_(cast_environment), |
| 33 target_playout_delay_(base::TimeDelta::FromMilliseconds( | 33 target_playout_delay_(base::TimeDelta::FromMilliseconds( |
| 34 video_config.rtp_config.max_delay_ms)), | 34 video_config.rtp_config.max_delay_ms)), |
| 35 transport_sender_(transport_sender), | 35 transport_sender_(transport_sender), |
| 36 max_unacked_frames_(std::min( | 36 max_unacked_frames_( |
| 37 kMaxUnackedFrames, | 37 std::min(kMaxUnackedFrames, |
| 38 1 + static_cast<int>( | 38 1 + static_cast<int>(target_playout_delay_ * |
| 39 target_playout_delay_ * video_config.max_frame_rate / | 39 video_config.max_frame_rate / |
| 40 base::TimeDelta::FromSeconds(1)))), | 40 base::TimeDelta::FromSeconds(1)))), |
| 41 rtcp_(cast_environment_, | 41 rtcp_(cast_environment_, |
| 42 this, | 42 this, |
| 43 transport_sender_, | 43 transport_sender_, |
| 44 NULL, // paced sender. | 44 NULL, // paced sender. |
| 45 NULL, | 45 NULL, |
| 46 video_config.rtcp_mode, | 46 video_config.rtcp_mode, |
| 47 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), | 47 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), |
| 48 video_config.rtp_config.ssrc, | 48 video_config.rtp_config.ssrc, |
| 49 video_config.incoming_feedback_ssrc, | 49 video_config.incoming_feedback_ssrc, |
| 50 video_config.rtcp_c_name, | 50 video_config.rtcp_c_name, |
| 51 VIDEO_EVENT), | 51 VIDEO_EVENT), |
| 52 rtp_timestamp_helper_(kVideoFrequency), | 52 rtp_timestamp_helper_(kVideoFrequency), |
| 53 num_aggressive_rtcp_reports_sent_(0), | 53 num_aggressive_rtcp_reports_sent_(0), |
| 54 frames_in_encoder_(0), | 54 frames_in_encoder_(0), |
| 55 last_sent_frame_id_(0), | 55 last_sent_frame_id_(0), |
| 56 latest_acked_frame_id_(0), | 56 latest_acked_frame_id_(0), |
| 57 duplicate_ack_counter_(0), | 57 duplicate_ack_counter_(0), |
| 58 current_requested_bitrate_(video_config.start_bitrate), | |
| 59 congestion_control_(cast_environment->Clock(), | 58 congestion_control_(cast_environment->Clock(), |
| 60 video_config.congestion_control_back_off, | |
| 61 video_config.max_bitrate, | 59 video_config.max_bitrate, |
| 62 video_config.min_bitrate, | 60 video_config.min_bitrate, |
| 63 video_config.start_bitrate), | 61 max_unacked_frames_), |
| 64 cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED), | 62 cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED), |
| 65 weak_factory_(this) { | 63 weak_factory_(this) { |
| 66 VLOG(1) << "max_unacked_frames " << max_unacked_frames_; | 64 VLOG(1) << "max_unacked_frames " << max_unacked_frames_; |
| 67 DCHECK_GT(max_unacked_frames_, 0); | 65 DCHECK_GT(max_unacked_frames_, 0); |
| 68 | 66 |
| 69 if (video_config.use_external_encoder) { | 67 if (video_config.use_external_encoder) { |
| 70 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, | 68 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, |
| 71 video_config, | 69 video_config, |
| 72 create_vea_cb, | 70 create_vea_cb, |
| 73 create_video_encode_mem_cb)); | 71 create_video_encode_mem_cb)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 "cast_perf_test", "InsertRawVideoFrame", | 114 "cast_perf_test", "InsertRawVideoFrame", |
| 117 TRACE_EVENT_SCOPE_THREAD, | 115 TRACE_EVENT_SCOPE_THREAD, |
| 118 "timestamp", capture_time.ToInternalValue(), | 116 "timestamp", capture_time.ToInternalValue(), |
| 119 "rtp_timestamp", rtp_timestamp); | 117 "rtp_timestamp", rtp_timestamp); |
| 120 | 118 |
| 121 if (AreTooManyFramesInFlight()) { | 119 if (AreTooManyFramesInFlight()) { |
| 122 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; | 120 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; |
| 123 return; | 121 return; |
| 124 } | 122 } |
| 125 | 123 |
| 124 uint32 bitrate = congestion_control_.GetBitrate( |
| 125 capture_time + target_playout_delay_, target_playout_delay_); |
| 126 |
| 127 video_encoder_->SetBitRate(bitrate); |
| 128 |
| 126 if (video_encoder_->EncodeVideoFrame( | 129 if (video_encoder_->EncodeVideoFrame( |
| 127 video_frame, | 130 video_frame, |
| 128 capture_time, | 131 capture_time, |
| 129 base::Bind(&VideoSender::SendEncodedVideoFrame, | 132 base::Bind(&VideoSender::SendEncodedVideoFrame, |
| 130 weak_factory_.GetWeakPtr(), | 133 weak_factory_.GetWeakPtr(), |
| 131 current_requested_bitrate_))) { | 134 bitrate))) { |
| 132 frames_in_encoder_++; | 135 frames_in_encoder_++; |
| 133 } else { | 136 } else { |
| 134 VLOG(1) << "Encoder rejected a frame. Skipping..."; | 137 VLOG(1) << "Encoder rejected a frame. Skipping..."; |
| 135 } | 138 } |
| 136 } | 139 } |
| 137 | 140 |
| 138 void VideoSender::SendEncodedVideoFrame( | 141 void VideoSender::SendEncodedVideoFrame( |
| 139 int requested_bitrate_before_encode, | 142 int requested_bitrate_before_encode, |
| 140 scoped_ptr<transport::EncodedFrame> encoded_frame) { | 143 scoped_ptr<transport::EncodedFrame> encoded_frame) { |
| 141 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 144 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 188 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
| 186 // SendRtcpReport() will schedule future reports to be made if this is the | 189 // SendRtcpReport() will schedule future reports to be made if this is the |
| 187 // last "aggressive report." | 190 // last "aggressive report." |
| 188 ++num_aggressive_rtcp_reports_sent_; | 191 ++num_aggressive_rtcp_reports_sent_; |
| 189 const bool is_last_aggressive_report = | 192 const bool is_last_aggressive_report = |
| 190 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); | 193 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); |
| 191 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report."; | 194 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report."; |
| 192 SendRtcpReport(is_last_aggressive_report); | 195 SendRtcpReport(is_last_aggressive_report); |
| 193 } | 196 } |
| 194 | 197 |
| 198 congestion_control_.SendFrameToTransport( |
| 199 frame_id, encoded_frame->data.size() * 8, last_send_time_); |
| 200 |
| 195 transport_sender_->InsertCodedVideoFrame(*encoded_frame); | 201 transport_sender_->InsertCodedVideoFrame(*encoded_frame); |
| 196 } | 202 } |
| 197 | 203 |
| 198 void VideoSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) { | 204 void VideoSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) { |
| 199 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 205 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 200 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); | 206 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); |
| 201 } | 207 } |
| 202 | 208 |
| 203 void VideoSender::ScheduleNextRtcpReport() { | 209 void VideoSender::ScheduleNextRtcpReport() { |
| 204 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 210 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 } | 270 } |
| 265 | 271 |
| 266 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { | 272 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { |
| 267 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 273 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 268 | 274 |
| 269 base::TimeDelta rtt; | 275 base::TimeDelta rtt; |
| 270 base::TimeDelta avg_rtt; | 276 base::TimeDelta avg_rtt; |
| 271 base::TimeDelta min_rtt; | 277 base::TimeDelta min_rtt; |
| 272 base::TimeDelta max_rtt; | 278 base::TimeDelta max_rtt; |
| 273 if (rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt)) { | 279 if (rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt)) { |
| 280 congestion_control_.UpdateRTT(rtt); |
| 281 |
| 274 // Don't use a RTT lower than our average. | 282 // Don't use a RTT lower than our average. |
| 275 rtt = std::max(rtt, avg_rtt); | 283 rtt = std::max(rtt, avg_rtt); |
| 276 | 284 |
| 277 // Having the RTT values implies the receiver sent back a receiver report | 285 // Having the RTT values implies the receiver sent back a receiver report |
| 278 // based on it having received a report from here. Therefore, ensure this | 286 // based on it having received a report from here. Therefore, ensure this |
| 279 // sender stops aggressively sending reports. | 287 // sender stops aggressively sending reports. |
| 280 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 288 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
| 281 VLOG(1) << "No longer a need to send reports aggressively (sent " | 289 VLOG(1) << "No longer a need to send reports aggressively (sent " |
| 282 << num_aggressive_rtcp_reports_sent_ << ")."; | 290 << num_aggressive_rtcp_reports_sent_ << ")."; |
| 283 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart; | 291 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart; |
| 284 ScheduleNextRtcpReport(); | 292 ScheduleNextRtcpReport(); |
| 285 } | 293 } |
| 286 } else { | 294 } else { |
| 287 // We have no measured value use default. | 295 // We have no measured value use default. |
| 288 rtt = base::TimeDelta::FromMilliseconds(kStartRttMs); | 296 rtt = base::TimeDelta::FromMilliseconds(kStartRttMs); |
| 289 } | 297 } |
| 290 | 298 |
| 291 if (last_send_time_.is_null()) | 299 if (last_send_time_.is_null()) |
| 292 return; // Cannot get an ACK without having first sent a frame. | 300 return; // Cannot get an ACK without having first sent a frame. |
| 293 | 301 |
| 294 if (cast_feedback.missing_frames_and_packets_.empty()) { | 302 if (cast_feedback.missing_frames_and_packets_.empty()) { |
| 295 video_encoder_->LatestFrameIdToReference(cast_feedback.ack_frame_id_); | 303 video_encoder_->LatestFrameIdToReference(cast_feedback.ack_frame_id_); |
| 296 | 304 |
| 297 if ((latest_acked_frame_id_ + 1) == cast_feedback.ack_frame_id_) { | |
| 298 uint32 new_bitrate = 0; | |
| 299 if (congestion_control_.OnAck(rtt, &new_bitrate)) { | |
| 300 UpdateBitrate(new_bitrate); | |
| 301 } | |
| 302 } | |
| 303 // We only count duplicate ACKs when we have sent newer frames. | 305 // We only count duplicate ACKs when we have sent newer frames. |
| 304 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id_ && | 306 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id_ && |
| 305 latest_acked_frame_id_ != last_sent_frame_id_) { | 307 latest_acked_frame_id_ != last_sent_frame_id_) { |
| 306 duplicate_ack_counter_++; | 308 duplicate_ack_counter_++; |
| 307 } else { | 309 } else { |
| 308 duplicate_ack_counter_ = 0; | 310 duplicate_ack_counter_ = 0; |
| 309 } | 311 } |
| 310 // TODO(miu): The values "2" and "3" should be derived from configuration. | 312 // TODO(miu): The values "2" and "3" should be derived from configuration. |
| 311 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { | 313 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { |
| 312 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; | 314 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; |
| 313 ResendForKickstart(); | 315 ResendForKickstart(); |
| 314 } | 316 } |
| 315 } else { | 317 } else { |
| 316 // Only count duplicated ACKs if there is no NACK request in between. | 318 // Only count duplicated ACKs if there is no NACK request in between. |
| 317 // This is to avoid aggresive resend. | 319 // This is to avoid aggresive resend. |
| 318 duplicate_ack_counter_ = 0; | 320 duplicate_ack_counter_ = 0; |
| 319 transport_sender_->ResendPackets( | 321 transport_sender_->ResendPackets( |
| 320 false, cast_feedback.missing_frames_and_packets_); | 322 false, cast_feedback.missing_frames_and_packets_); |
| 321 uint32 new_bitrate = 0; | |
| 322 if (congestion_control_.OnNack(rtt, &new_bitrate)) { | |
| 323 UpdateBitrate(new_bitrate); | |
| 324 } | |
| 325 } | 323 } |
| 326 | 324 |
| 325 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 326 congestion_control_.AckFrame(cast_feedback.ack_frame_id_, now); |
| 327 |
| 327 RtpTimestamp rtp_timestamp = | 328 RtpTimestamp rtp_timestamp = |
| 328 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff]; | 329 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff]; |
| 329 cast_environment_->Logging()->InsertFrameEvent( | 330 cast_environment_->Logging()->InsertFrameEvent(now, |
| 330 cast_environment_->Clock()->NowTicks(), FRAME_ACK_RECEIVED, VIDEO_EVENT, | 331 FRAME_ACK_RECEIVED, |
| 331 rtp_timestamp, cast_feedback.ack_frame_id_); | 332 VIDEO_EVENT, |
| 333 rtp_timestamp, |
| 334 cast_feedback.ack_frame_id_); |
| 332 | 335 |
| 333 const bool is_acked_out_of_order = | 336 const bool is_acked_out_of_order = |
| 334 static_cast<int32>(cast_feedback.ack_frame_id_ - | 337 static_cast<int32>(cast_feedback.ack_frame_id_ - |
| 335 latest_acked_frame_id_) < 0; | 338 latest_acked_frame_id_) < 0; |
| 336 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") | 339 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") |
| 337 << " for frame " << cast_feedback.ack_frame_id_; | 340 << " for frame " << cast_feedback.ack_frame_id_; |
| 338 if (!is_acked_out_of_order) | 341 if (!is_acked_out_of_order) |
| 339 latest_acked_frame_id_ = cast_feedback.ack_frame_id_; | 342 latest_acked_frame_id_ = cast_feedback.ack_frame_id_; |
| 340 } | 343 } |
| 341 | 344 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 363 // packets and frames are missing. | 366 // packets and frames are missing. |
| 364 MissingFramesAndPacketsMap missing_frames_and_packets; | 367 MissingFramesAndPacketsMap missing_frames_and_packets; |
| 365 PacketIdSet missing; | 368 PacketIdSet missing; |
| 366 missing.insert(0); | 369 missing.insert(0); |
| 367 missing_frames_and_packets.insert( | 370 missing_frames_and_packets.insert( |
| 368 std::make_pair(last_sent_frame_id_, missing)); | 371 std::make_pair(last_sent_frame_id_, missing)); |
| 369 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 372 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 370 transport_sender_->ResendPackets(false, missing_frames_and_packets); | 373 transport_sender_->ResendPackets(false, missing_frames_and_packets); |
| 371 } | 374 } |
| 372 | 375 |
| 373 void VideoSender::UpdateBitrate(int new_bitrate) { | |
| 374 // Make sure we don't set the bitrate too insanely low. | |
| 375 DCHECK_GT(new_bitrate, 1000); | |
| 376 video_encoder_->SetBitRate(new_bitrate); | |
| 377 current_requested_bitrate_ = new_bitrate; | |
| 378 } | |
| 379 | |
| 380 } // namespace cast | 376 } // namespace cast |
| 381 } // namespace media | 377 } // namespace media |
| OLD | NEW |