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 |