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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 : rtp_max_delay_(base::TimeDelta::FromMilliseconds( | 54 : rtp_max_delay_(base::TimeDelta::FromMilliseconds( |
| 55 video_config.rtp_config.max_delay_ms)), | 55 video_config.rtp_config.max_delay_ms)), |
| 56 max_frame_rate_(video_config.max_frame_rate), | 56 max_frame_rate_(video_config.max_frame_rate), |
| 57 cast_environment_(cast_environment), | 57 cast_environment_(cast_environment), |
| 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 duplicate_ack_(0), | 65 duplicate_ack_(0), |
| 65 last_skip_count_(0), | 66 last_skip_count_(0), |
| 66 current_requested_bitrate_(video_config.start_bitrate), | 67 current_requested_bitrate_(video_config.start_bitrate), |
| 67 congestion_control_(cast_environment->Clock(), | 68 congestion_control_(cast_environment->Clock(), |
| 68 video_config.congestion_control_back_off, | 69 video_config.congestion_control_back_off, |
| 69 video_config.max_bitrate, | 70 video_config.max_bitrate, |
| 70 video_config.min_bitrate, | 71 video_config.min_bitrate, |
| 71 video_config.start_bitrate), | 72 video_config.start_bitrate), |
| 72 initialized_(false), | 73 initialized_(false), |
| 73 active_session_(false), | 74 active_session_(false), |
| 74 weak_factory_(this) { | 75 weak_factory_(this) { |
| 75 max_unacked_frames_ = | 76 max_unacked_frames_ = |
| 76 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms * | 77 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms * |
| 77 max_frame_rate_ / 1000); | 78 max_frame_rate_ / 1000); |
| 78 VLOG(1) << "max_unacked_frames " << static_cast<int>(max_unacked_frames_); | 79 VLOG(1) << "max_unacked_frames " << static_cast<int>(max_unacked_frames_); |
| 79 DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument"; | 80 DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument"; |
| 80 | 81 |
| 81 if (video_config.use_external_encoder) { | 82 if (video_config.use_external_encoder) { |
| 82 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, | 83 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, |
| 83 video_config, | 84 video_config, |
| 84 create_vea_cb, | 85 create_vea_cb, |
| 85 create_video_encode_mem_cb)); | 86 create_video_encode_mem_cb)); |
| 86 } else { | 87 } else { |
| 87 video_encoder_.reset(new VideoEncoderImpl( | 88 video_encoder_.reset(new VideoEncoderImpl( |
| 88 cast_environment, video_config, max_unacked_frames_)); | 89 cast_environment, video_config, max_unacked_frames_)); |
| 89 } | 90 } |
| 90 | 91 |
| 92 | |
| 93 media::cast::transport::CastTransportVideoConfig transport_config; | |
| 94 transport_config.codec = video_config.codec; | |
| 95 transport_config.rtp.config = video_config.rtp_config; | |
| 96 transport_config.rtp.max_outstanding_frames = max_unacked_frames_ + 1; | |
| 97 transport_sender_->InitializeVideo(transport_config); | |
| 98 | |
| 91 rtcp_.reset( | 99 rtcp_.reset( |
| 92 new Rtcp(cast_environment_, | 100 new Rtcp(cast_environment_, |
| 93 rtcp_feedback_.get(), | 101 rtcp_feedback_.get(), |
| 94 transport_sender_, | 102 transport_sender_, |
| 95 NULL, // paced sender. | 103 NULL, // paced sender. |
| 96 NULL, | 104 NULL, |
| 97 video_config.rtcp_mode, | 105 video_config.rtcp_mode, |
| 98 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), | 106 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), |
| 99 video_config.sender_ssrc, | 107 video_config.rtp_config.ssrc, |
| 100 video_config.incoming_feedback_ssrc, | 108 video_config.incoming_feedback_ssrc, |
| 101 video_config.rtcp_c_name)); | 109 video_config.rtcp_c_name)); |
| 102 rtcp_->SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize); | 110 rtcp_->SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize); |
| 103 | 111 |
| 104 // TODO(pwestin): pass cast_initialization_cb to |video_encoder_| | 112 // TODO(pwestin): pass cast_initialization_cb to |video_encoder_| |
| 105 // and remove this call. | 113 // and remove this call. |
| 106 cast_environment_->PostTask( | 114 cast_environment_->PostTask( |
| 107 CastEnvironment::MAIN, | 115 CastEnvironment::MAIN, |
| 108 FROM_HERE, | 116 FROM_HERE, |
| 109 base::Bind(cast_initialization_cb, STATUS_VIDEO_INITIALIZED)); | 117 base::Bind(cast_initialization_cb, STATUS_VIDEO_INITIALIZED)); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 rtp_timestamp, | 151 rtp_timestamp, |
| 144 kFrameIdUnknown); | 152 kFrameIdUnknown); |
| 145 | 153 |
| 146 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 154 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 147 TRACE_EVENT_INSTANT2( | 155 TRACE_EVENT_INSTANT2( |
| 148 "cast_perf_test", "InsertRawVideoFrame", | 156 "cast_perf_test", "InsertRawVideoFrame", |
| 149 TRACE_EVENT_SCOPE_THREAD, | 157 TRACE_EVENT_SCOPE_THREAD, |
| 150 "timestamp", capture_time.ToInternalValue(), | 158 "timestamp", capture_time.ToInternalValue(), |
| 151 "rtp_timestamp", GetVideoRtpTimestamp(capture_time)); | 159 "rtp_timestamp", GetVideoRtpTimestamp(capture_time)); |
| 152 | 160 |
| 153 if (!video_encoder_->EncodeVideoFrame( | 161 if (video_encoder_->EncodeVideoFrame( |
| 154 video_frame, | 162 video_frame, |
| 155 capture_time, | 163 capture_time, |
| 156 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread, | 164 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread, |
| 157 weak_factory_.GetWeakPtr()))) { | 165 weak_factory_.GetWeakPtr()))) { |
| 166 frames_in_encoder_++; | |
| 167 UpdateFramesInFlight(); | |
| 158 } | 168 } |
| 159 } | 169 } |
| 160 | 170 |
| 161 void VideoSender::SendEncodedVideoFrameMainThread( | 171 void VideoSender::SendEncodedVideoFrameMainThread( |
| 162 scoped_ptr<transport::EncodedVideoFrame> encoded_frame, | 172 scoped_ptr<transport::EncodedVideoFrame> encoded_frame, |
| 163 const base::TimeTicks& capture_time) { | 173 const base::TimeTicks& capture_time) { |
| 164 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 174 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 165 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 175 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 166 if (encoded_frame->key_frame) { | 176 if (encoded_frame->key_frame) { |
| 167 VLOG(1) << "Send encoded key frame; frame_id:" | 177 VLOG(1) << "Send encoded key frame; frame_id:" |
| 168 << static_cast<int>(encoded_frame->frame_id); | 178 << static_cast<int>(encoded_frame->frame_id); |
| 169 } | 179 } |
| 170 | 180 |
| 181 DCHECK_GT(frames_in_encoder_, 0); | |
| 182 frames_in_encoder_--; | |
| 171 uint32 frame_id = encoded_frame->frame_id; | 183 uint32 frame_id = encoded_frame->frame_id; |
| 172 cast_environment_->Logging()->InsertEncodedFrameEvent( | 184 cast_environment_->Logging()->InsertEncodedFrameEvent( |
| 173 last_send_time_, kVideoFrameEncoded, encoded_frame->rtp_timestamp, | 185 last_send_time_, kVideoFrameEncoded, encoded_frame->rtp_timestamp, |
| 174 frame_id, static_cast<int>(encoded_frame->data.size()), | 186 frame_id, static_cast<int>(encoded_frame->data.size()), |
| 175 encoded_frame->key_frame, current_requested_bitrate_); | 187 encoded_frame->key_frame, current_requested_bitrate_); |
| 176 | 188 |
| 177 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 189 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 178 TRACE_EVENT_INSTANT1( | 190 TRACE_EVENT_INSTANT1( |
| 179 "cast_perf_test", "VideoFrameEncoded", | 191 "cast_perf_test", "VideoFrameEncoded", |
| 180 TRACE_EVENT_SCOPE_THREAD, | 192 TRACE_EVENT_SCOPE_THREAD, |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) { | 301 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) { |
| 290 base::TimeDelta time_since_last_send = | 302 base::TimeDelta time_since_last_send = |
| 291 cast_environment_->Clock()->NowTicks() - last_send_time_; | 303 cast_environment_->Clock()->NowTicks() - last_send_time_; |
| 292 if (time_since_last_send > rtp_max_delay_) { | 304 if (time_since_last_send > rtp_max_delay_) { |
| 293 if (!active_session_) { | 305 if (!active_session_) { |
| 294 // We have not received any acks, resend the first encoded frame (id 0), | 306 // We have not received any acks, resend the first encoded frame (id 0), |
| 295 // which must also be a key frame. | 307 // which must also be a key frame. |
| 296 VLOG(1) << "ACK timeout resend first key frame"; | 308 VLOG(1) << "ACK timeout resend first key frame"; |
| 297 ResendFrame(0); | 309 ResendFrame(0); |
| 298 } else { | 310 } else { |
| 299 DCHECK_LE(0, last_acked_frame_id_); | 311 if (last_acked_frame_id_ == last_sent_frame_id_) { |
| 300 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1); | 312 // Last frame acked, no point in doing anything |
|
Alpha Left Google
2014/04/29 00:55:05
Please have a test for this case. This is a third
hubbe
2014/04/29 17:19:58
Actually, the problem is that without this if-stat
| |
| 301 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id); | 313 } else { |
| 302 ResendFrame(frame_id); | 314 DCHECK_LE(0, last_acked_frame_id_); |
| 315 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1); | |
| 316 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id); | |
| 317 ResendFrame(frame_id); | |
| 318 } | |
| 303 } | 319 } |
| 304 } | 320 } |
| 305 } | 321 } |
| 306 ScheduleNextResendCheck(); | 322 ScheduleNextResendCheck(); |
| 307 } | 323 } |
| 308 | 324 |
| 309 void VideoSender::ScheduleNextSkippedFramesCheck() { | 325 void VideoSender::ScheduleNextSkippedFramesCheck() { |
| 310 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 326 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 311 base::TimeDelta time_to_next; | 327 base::TimeDelta time_to_next; |
| 312 if (last_checked_skip_count_time_.is_null()) { | 328 if (last_checked_skip_count_time_.is_null()) { |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 if (last_sent_frame_id_ != -1) { | 452 if (last_sent_frame_id_ != -1) { |
| 437 DCHECK_LE(0, last_sent_frame_id_); | 453 DCHECK_LE(0, last_sent_frame_id_); |
| 438 uint32 frames_in_flight = 0; | 454 uint32 frames_in_flight = 0; |
| 439 if (last_acked_frame_id_ != -1) { | 455 if (last_acked_frame_id_ != -1) { |
| 440 DCHECK_LE(0, last_acked_frame_id_); | 456 DCHECK_LE(0, last_acked_frame_id_); |
| 441 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) - | 457 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) - |
| 442 static_cast<uint32>(last_acked_frame_id_); | 458 static_cast<uint32>(last_acked_frame_id_); |
| 443 } else { | 459 } else { |
| 444 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; | 460 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; |
| 445 } | 461 } |
| 462 frames_in_flight += frames_in_encoder_; | |
| 446 VLOG(2) << frames_in_flight | 463 VLOG(2) << frames_in_flight |
| 447 << " Frames in flight; last sent: " << last_sent_frame_id_ | 464 << " Frames in flight; last sent: " << last_sent_frame_id_ |
| 448 << " last acked:" << last_acked_frame_id_; | 465 << " last acked:" << last_acked_frame_id_ |
| 466 << " frames in encoder: " << frames_in_encoder_; | |
| 449 if (frames_in_flight >= max_unacked_frames_) { | 467 if (frames_in_flight >= max_unacked_frames_) { |
| 450 video_encoder_->SkipNextFrame(true); | 468 video_encoder_->SkipNextFrame(true); |
| 451 return; | 469 return; |
| 452 } | 470 } |
| 453 DCHECK(frames_in_flight <= max_unacked_frames_); | 471 DCHECK(frames_in_flight <= max_unacked_frames_); |
| 454 } | 472 } |
| 455 video_encoder_->SkipNextFrame(false); | 473 video_encoder_->SkipNextFrame(false); |
| 456 } | 474 } |
| 457 | 475 |
| 458 void VideoSender::ResendFrame(uint32 resend_frame_id) { | 476 void VideoSender::ResendFrame(uint32 resend_frame_id) { |
| 459 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 477 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 460 MissingFramesAndPacketsMap missing_frames_and_packets; | 478 MissingFramesAndPacketsMap missing_frames_and_packets; |
| 461 PacketIdSet missing; | 479 PacketIdSet missing; |
| 462 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); | 480 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); |
| 463 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 481 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 464 transport_sender_->ResendPackets(false, missing_frames_and_packets); | 482 transport_sender_->ResendPackets(false, missing_frames_and_packets); |
| 465 } | 483 } |
| 466 | 484 |
| 467 } // namespace cast | 485 } // namespace cast |
| 468 } // namespace media | 486 } // namespace media |
| OLD | NEW |