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/sender/video_sender.h" | 5 #include "media/cast/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" |
11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
14 #include "media/cast/cast_defines.h" | 14 #include "media/cast/cast_defines.h" |
15 #include "media/cast/net/cast_transport_config.h" | 15 #include "media/cast/net/cast_transport_config.h" |
16 #include "media/cast/net/rtcp/rtcp_defines.h" | 16 #include "media/cast/net/rtcp/rtcp_defines.h" |
miu
2014/07/16 19:58:03
Remove this include.
Alpha Left Google
2014/07/17 01:01:46
Done.
| |
17 #include "media/cast/sender/external_video_encoder.h" | 17 #include "media/cast/sender/external_video_encoder.h" |
18 #include "media/cast/sender/video_encoder_impl.h" | 18 #include "media/cast/sender/video_encoder_impl.h" |
19 | 19 |
20 namespace media { | 20 namespace media { |
21 namespace cast { | 21 namespace cast { |
22 | 22 |
23 const int kNumAggressiveReportsSentAtStart = 100; | 23 const int kNumAggressiveReportsSentAtStart = 100; |
24 const int kMinSchedulingDelayMs = 1; | 24 const int kMinSchedulingDelayMs = 1; |
25 | 25 |
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 CastTransportSender* const transport_sender) | 31 CastTransportSender* const transport_sender) |
32 : cast_environment_(cast_environment), | 32 : FrameSender( |
33 cast_environment, | |
34 transport_sender, | |
35 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), | |
36 kVideoFrequency, | |
37 false), | |
33 target_playout_delay_(video_config.target_playout_delay), | 38 target_playout_delay_(video_config.target_playout_delay), |
34 transport_sender_(transport_sender), | |
35 max_unacked_frames_( | 39 max_unacked_frames_( |
36 std::min(kMaxUnackedFrames, | 40 std::min(kMaxUnackedFrames, |
37 1 + static_cast<int>(target_playout_delay_ * | 41 1 + static_cast<int>(target_playout_delay_ * |
38 video_config.max_frame_rate / | 42 video_config.max_frame_rate / |
39 base::TimeDelta::FromSeconds(1)))), | 43 base::TimeDelta::FromSeconds(1)))), |
40 rtcp_(cast_environment_, | |
41 this, | |
42 transport_sender_, | |
43 NULL, // paced sender. | |
44 NULL, | |
45 video_config.rtcp_mode, | |
46 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), | |
47 video_config.ssrc, | |
48 video_config.incoming_feedback_ssrc, | |
49 video_config.rtcp_c_name, | |
50 VIDEO_EVENT), | |
51 rtp_timestamp_helper_(kVideoFrequency), | |
52 num_aggressive_rtcp_reports_sent_(0), | 44 num_aggressive_rtcp_reports_sent_(0), |
53 frames_in_encoder_(0), | 45 frames_in_encoder_(0), |
54 last_sent_frame_id_(0), | 46 last_sent_frame_id_(0), |
55 latest_acked_frame_id_(0), | 47 latest_acked_frame_id_(0), |
56 duplicate_ack_counter_(0), | 48 duplicate_ack_counter_(0), |
57 congestion_control_(cast_environment->Clock(), | 49 congestion_control_(cast_environment->Clock(), |
58 video_config.max_bitrate, | 50 video_config.max_bitrate, |
59 video_config.min_bitrate, | 51 video_config.min_bitrate, |
60 max_unacked_frames_), | 52 max_unacked_frames_), |
61 cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED), | 53 cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED), |
62 weak_factory_(this) { | 54 weak_factory_(this) { |
63 VLOG(1) << "max_unacked_frames " << max_unacked_frames_; | 55 VLOG(1) << "max_unacked_frames " << max_unacked_frames_; |
64 DCHECK_GT(max_unacked_frames_, 0); | 56 DCHECK_GT(max_unacked_frames_, 0); |
65 | 57 |
66 if (video_config.use_external_encoder) { | 58 if (video_config.use_external_encoder) { |
67 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, | 59 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, |
68 video_config, | 60 video_config, |
69 create_vea_cb, | 61 create_vea_cb, |
70 create_video_encode_mem_cb)); | 62 create_video_encode_mem_cb)); |
71 } else { | 63 } else { |
72 video_encoder_.reset(new VideoEncoderImpl( | 64 video_encoder_.reset(new VideoEncoderImpl( |
73 cast_environment, video_config, max_unacked_frames_)); | 65 cast_environment, video_config, max_unacked_frames_)); |
74 } | 66 } |
75 cast_initialization_status_ = STATUS_VIDEO_INITIALIZED; | 67 cast_initialization_status_ = STATUS_VIDEO_INITIALIZED; |
76 | 68 |
77 media::cast::CastTransportRtpConfig transport_config; | 69 media::cast::CastTransportRtpConfig transport_config; |
78 transport_config.ssrc = video_config.ssrc; | 70 transport_config.ssrc = video_config.ssrc; |
71 transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc; | |
72 transport_config.c_name = video_config.rtcp_c_name; | |
79 transport_config.rtp_payload_type = video_config.rtp_payload_type; | 73 transport_config.rtp_payload_type = video_config.rtp_payload_type; |
80 transport_config.stored_frames = max_unacked_frames_; | 74 transport_config.stored_frames = max_unacked_frames_; |
81 transport_config.aes_key = video_config.aes_key; | 75 transport_config.aes_key = video_config.aes_key; |
82 transport_config.aes_iv_mask = video_config.aes_iv_mask; | 76 transport_config.aes_iv_mask = video_config.aes_iv_mask; |
83 transport_sender_->InitializeVideo(transport_config); | |
84 | 77 |
85 rtcp_.SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize); | 78 transport_sender->InitializeVideo( |
79 transport_config, | |
80 base::Bind(&VideoSender::OnReceivedCastFeedback, | |
81 weak_factory_.GetWeakPtr()), | |
82 base::Bind(&VideoSender::OnReceivedRtt, weak_factory_.GetWeakPtr())); | |
86 | 83 |
87 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); | 84 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); |
88 } | 85 } |
89 | 86 |
90 VideoSender::~VideoSender() { | 87 VideoSender::~VideoSender() { |
91 } | 88 } |
92 | 89 |
93 void VideoSender::InsertRawVideoFrame( | 90 void VideoSender::InsertRawVideoFrame( |
94 const scoped_refptr<media::VideoFrame>& video_frame, | 91 const scoped_refptr<media::VideoFrame>& video_frame, |
95 const base::TimeTicks& capture_time) { | 92 const base::TimeTicks& capture_time) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report."; | 192 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report."; |
196 SendRtcpReport(is_last_aggressive_report); | 193 SendRtcpReport(is_last_aggressive_report); |
197 } | 194 } |
198 | 195 |
199 congestion_control_.SendFrameToTransport( | 196 congestion_control_.SendFrameToTransport( |
200 frame_id, encoded_frame->data.size() * 8, last_send_time_); | 197 frame_id, encoded_frame->data.size() * 8, last_send_time_); |
201 | 198 |
202 transport_sender_->InsertCodedVideoFrame(*encoded_frame); | 199 transport_sender_->InsertCodedVideoFrame(*encoded_frame); |
203 } | 200 } |
204 | 201 |
205 void VideoSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) { | 202 void VideoSender::ResendCheck() { |
206 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 203 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
207 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size()); | 204 DCHECK(!last_send_time_.is_null()); |
208 } | 205 const base::TimeDelta time_since_last_send = |
209 | 206 cast_environment_->Clock()->NowTicks() - last_send_time_; |
210 void VideoSender::ScheduleNextRtcpReport() { | 207 if (time_since_last_send > target_playout_delay_) { |
211 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 208 if (latest_acked_frame_id_ == last_sent_frame_id_) { |
212 base::TimeDelta time_to_next = rtcp_.TimeToSendNextRtcpReport() - | 209 // Last frame acked, no point in doing anything |
213 cast_environment_->Clock()->NowTicks(); | 210 } else { |
214 | 211 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; |
215 time_to_next = std::max( | 212 ResendForKickstart(); |
216 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 213 } |
217 | |
218 cast_environment_->PostDelayedTask( | |
219 CastEnvironment::MAIN, | |
220 FROM_HERE, | |
221 base::Bind(&VideoSender::SendRtcpReport, | |
222 weak_factory_.GetWeakPtr(), | |
223 true), | |
224 time_to_next); | |
225 } | |
226 | |
227 void VideoSender::SendRtcpReport(bool schedule_future_reports) { | |
228 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | |
229 const base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | |
230 uint32 now_as_rtp_timestamp = 0; | |
231 if (rtp_timestamp_helper_.GetCurrentTimeAsRtpTimestamp( | |
232 now, &now_as_rtp_timestamp)) { | |
233 rtcp_.SendRtcpFromRtpSender(now, now_as_rtp_timestamp); | |
234 } else { | |
235 // |rtp_timestamp_helper_| should have stored a mapping by this point. | |
236 NOTREACHED(); | |
237 } | 214 } |
238 if (schedule_future_reports) | 215 ScheduleNextResendCheck(); |
239 ScheduleNextRtcpReport(); | |
240 } | 216 } |
241 | 217 |
242 void VideoSender::ScheduleNextResendCheck() { | 218 void VideoSender::ScheduleNextResendCheck() { |
243 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 219 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
244 DCHECK(!last_send_time_.is_null()); | 220 DCHECK(!last_send_time_.is_null()); |
245 base::TimeDelta time_to_next = | 221 base::TimeDelta time_to_next = |
246 last_send_time_ - cast_environment_->Clock()->NowTicks() + | 222 last_send_time_ - cast_environment_->Clock()->NowTicks() + |
247 target_playout_delay_; | 223 target_playout_delay_; |
248 time_to_next = std::max( | 224 time_to_next = std::max( |
249 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); | 225 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
250 cast_environment_->PostDelayedTask( | 226 cast_environment_->PostDelayedTask( |
251 CastEnvironment::MAIN, | 227 CastEnvironment::MAIN, |
252 FROM_HERE, | 228 FROM_HERE, |
253 base::Bind(&VideoSender::ResendCheck, weak_factory_.GetWeakPtr()), | 229 base::Bind(&VideoSender::ResendCheck, weak_factory_.GetWeakPtr()), |
254 time_to_next); | 230 time_to_next); |
255 } | 231 } |
256 | 232 |
257 void VideoSender::ResendCheck() { | |
258 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | |
259 DCHECK(!last_send_time_.is_null()); | |
260 const base::TimeDelta time_since_last_send = | |
261 cast_environment_->Clock()->NowTicks() - last_send_time_; | |
262 if (time_since_last_send > target_playout_delay_) { | |
263 if (latest_acked_frame_id_ == last_sent_frame_id_) { | |
264 // Last frame acked, no point in doing anything | |
265 } else { | |
266 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; | |
267 ResendForKickstart(); | |
268 } | |
269 } | |
270 ScheduleNextResendCheck(); | |
271 } | |
272 | |
273 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { | 233 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { |
274 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 234 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
275 | 235 |
276 base::TimeDelta rtt; | 236 base::TimeDelta rtt; |
277 base::TimeDelta avg_rtt; | 237 base::TimeDelta avg_rtt; |
278 base::TimeDelta min_rtt; | 238 base::TimeDelta min_rtt; |
279 base::TimeDelta max_rtt; | 239 base::TimeDelta max_rtt; |
280 if (rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt)) { | 240 if (is_rtt_available()) { |
241 rtt = rtt_; | |
242 avg_rtt = avg_rtt_; | |
243 min_rtt = min_rtt_; | |
244 max_rtt = max_rtt_; | |
245 | |
281 congestion_control_.UpdateRtt(rtt); | 246 congestion_control_.UpdateRtt(rtt); |
282 | 247 |
283 // Don't use a RTT lower than our average. | 248 // Don't use a RTT lower than our average. |
284 rtt = std::max(rtt, avg_rtt); | 249 rtt = std::max(rtt, avg_rtt); |
285 | 250 |
286 // Having the RTT values implies the receiver sent back a receiver report | 251 // Having the RTT values implies the receiver sent back a receiver report |
287 // based on it having received a report from here. Therefore, ensure this | 252 // based on it having received a report from here. Therefore, ensure this |
288 // sender stops aggressively sending reports. | 253 // sender stops aggressively sending reports. |
289 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 254 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
290 VLOG(1) << "No longer a need to send reports aggressively (sent " | 255 VLOG(1) << "No longer a need to send reports aggressively (sent " |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 // Send the first packet of the last encoded frame to kick start | 342 // Send the first packet of the last encoded frame to kick start |
378 // retransmission. This gives enough information to the receiver what | 343 // retransmission. This gives enough information to the receiver what |
379 // packets and frames are missing. | 344 // packets and frames are missing. |
380 MissingFramesAndPacketsMap missing_frames_and_packets; | 345 MissingFramesAndPacketsMap missing_frames_and_packets; |
381 PacketIdSet missing; | 346 PacketIdSet missing; |
382 missing.insert(kRtcpCastLastPacket); | 347 missing.insert(kRtcpCastLastPacket); |
383 missing_frames_and_packets.insert( | 348 missing_frames_and_packets.insert( |
384 std::make_pair(last_sent_frame_id_, missing)); | 349 std::make_pair(last_sent_frame_id_, missing)); |
385 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 350 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
386 | 351 |
387 base::TimeDelta rtt; | |
388 base::TimeDelta avg_rtt; | |
389 base::TimeDelta min_rtt; | |
390 base::TimeDelta max_rtt; | |
391 rtcp_.Rtt(&rtt, &avg_rtt, &min_rtt, &max_rtt); | |
392 | |
393 // Sending this extra packet is to kick-start the session. There is | 352 // Sending this extra packet is to kick-start the session. There is |
394 // no need to optimize re-transmission for this case. | 353 // no need to optimize re-transmission for this case. |
395 transport_sender_->ResendPackets(false, missing_frames_and_packets, | 354 transport_sender_->ResendPackets(false, missing_frames_and_packets, |
396 false, rtt); | 355 false, rtt_); |
397 } | 356 } |
398 | 357 |
399 } // namespace cast | 358 } // namespace cast |
400 } // namespace media | 359 } // namespace media |
OLD | NEW |