| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 rtp_timestamp, | 112 rtp_timestamp, |
| 113 kFrameIdUnknown); | 113 kFrameIdUnknown); |
| 114 | 114 |
| 115 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 115 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 116 TRACE_EVENT_INSTANT2( | 116 TRACE_EVENT_INSTANT2( |
| 117 "cast_perf_test", "InsertRawVideoFrame", | 117 "cast_perf_test", "InsertRawVideoFrame", |
| 118 TRACE_EVENT_SCOPE_THREAD, | 118 TRACE_EVENT_SCOPE_THREAD, |
| 119 "timestamp", capture_time.ToInternalValue(), | 119 "timestamp", capture_time.ToInternalValue(), |
| 120 "rtp_timestamp", rtp_timestamp); | 120 "rtp_timestamp", rtp_timestamp); |
| 121 | 121 |
| 122 if (AreTooManyFramesInFlight()) { | 122 if (ShouldDropNextFrame(capture_time)) { |
| 123 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; | 123 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; |
| 124 return; | 124 return; |
| 125 } | 125 } |
| 126 | 126 |
| 127 uint32 bitrate = fixed_bitrate_; | 127 uint32 bitrate = fixed_bitrate_; |
| 128 if (!bitrate) { | 128 if (!bitrate) { |
| 129 bitrate = congestion_control_.GetBitrate( | 129 bitrate = congestion_control_.GetBitrate( |
| 130 capture_time + target_playout_delay_, target_playout_delay_); | 130 capture_time + target_playout_delay_, target_playout_delay_); |
| 131 DCHECK(bitrate); | 131 DCHECK(bitrate); |
| 132 video_encoder_->SetBitRate(bitrate); | 132 video_encoder_->SetBitRate(bitrate); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 } | 171 } |
| 172 | 172 |
| 173 VLOG_IF(1, encoded_frame->dependency == EncodedFrame::KEY) | 173 VLOG_IF(1, encoded_frame->dependency == EncodedFrame::KEY) |
| 174 << "Send encoded key frame; frame_id: " << frame_id; | 174 << "Send encoded key frame; frame_id: " << frame_id; |
| 175 | 175 |
| 176 cast_environment_->Logging()->InsertEncodedFrameEvent( | 176 cast_environment_->Logging()->InsertEncodedFrameEvent( |
| 177 last_send_time_, FRAME_ENCODED, VIDEO_EVENT, encoded_frame->rtp_timestamp, | 177 last_send_time_, FRAME_ENCODED, VIDEO_EVENT, encoded_frame->rtp_timestamp, |
| 178 frame_id, static_cast<int>(encoded_frame->data.size()), | 178 frame_id, static_cast<int>(encoded_frame->data.size()), |
| 179 encoded_frame->dependency == EncodedFrame::KEY, | 179 encoded_frame->dependency == EncodedFrame::KEY, |
| 180 requested_bitrate_before_encode); | 180 requested_bitrate_before_encode); |
| 181 // Only use lowest 8 bits as key. | 181 |
| 182 frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp; | 182 RecordLatestFrameTimestamps(frame_id, |
| 183 encoded_frame->reference_time, |
| 184 encoded_frame->rtp_timestamp); |
| 183 | 185 |
| 184 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 186 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 185 TRACE_EVENT_INSTANT1( | 187 TRACE_EVENT_INSTANT1( |
| 186 "cast_perf_test", "VideoFrameEncoded", | 188 "cast_perf_test", "VideoFrameEncoded", |
| 187 TRACE_EVENT_SCOPE_THREAD, | 189 TRACE_EVENT_SCOPE_THREAD, |
| 188 "rtp_timestamp", encoded_frame->rtp_timestamp); | 190 "rtp_timestamp", encoded_frame->rtp_timestamp); |
| 189 | 191 |
| 190 DCHECK(!encoded_frame->reference_time.is_null()); | |
| 191 rtp_timestamp_helper_.StoreLatestTime(encoded_frame->reference_time, | |
| 192 encoded_frame->rtp_timestamp); | |
| 193 | |
| 194 // At the start of the session, it's important to send reports before each | 192 // At the start of the session, it's important to send reports before each |
| 195 // frame so that the receiver can properly compute playout times. The reason | 193 // frame so that the receiver can properly compute playout times. The reason |
| 196 // more than one report is sent is because transmission is not guaranteed, | 194 // more than one report is sent is because transmission is not guaranteed, |
| 197 // only best effort, so send enough that one should almost certainly get | 195 // only best effort, so send enough that one should almost certainly get |
| 198 // through. | 196 // through. |
| 199 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 197 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
| 200 // SendRtcpReport() will schedule future reports to be made if this is the | 198 // SendRtcpReport() will schedule future reports to be made if this is the |
| 201 // last "aggressive report." | 199 // last "aggressive report." |
| 202 ++num_aggressive_rtcp_reports_sent_; | 200 ++num_aggressive_rtcp_reports_sent_; |
| 203 const bool is_last_aggressive_report = | 201 const bool is_last_aggressive_report = |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 } | 266 } |
| 269 } else { | 267 } else { |
| 270 // Only count duplicated ACKs if there is no NACK request in between. | 268 // Only count duplicated ACKs if there is no NACK request in between. |
| 271 // This is to avoid aggresive resend. | 269 // This is to avoid aggresive resend. |
| 272 duplicate_ack_counter_ = 0; | 270 duplicate_ack_counter_ = 0; |
| 273 } | 271 } |
| 274 | 272 |
| 275 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 273 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 276 congestion_control_.AckFrame(cast_feedback.ack_frame_id, now); | 274 congestion_control_.AckFrame(cast_feedback.ack_frame_id, now); |
| 277 | 275 |
| 278 RtpTimestamp rtp_timestamp = | 276 cast_environment_->Logging()->InsertFrameEvent( |
| 279 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff]; | 277 now, |
| 280 cast_environment_->Logging()->InsertFrameEvent(now, | 278 FRAME_ACK_RECEIVED, |
| 281 FRAME_ACK_RECEIVED, | 279 VIDEO_EVENT, |
| 282 VIDEO_EVENT, | 280 GetRecordedRtpTimestamp(cast_feedback.ack_frame_id), |
| 283 rtp_timestamp, | 281 cast_feedback.ack_frame_id); |
| 284 cast_feedback.ack_frame_id); | |
| 285 | 282 |
| 286 const bool is_acked_out_of_order = | 283 const bool is_acked_out_of_order = |
| 287 static_cast<int32>(cast_feedback.ack_frame_id - | 284 static_cast<int32>(cast_feedback.ack_frame_id - |
| 288 latest_acked_frame_id_) < 0; | 285 latest_acked_frame_id_) < 0; |
| 289 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") | 286 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") |
| 290 << " for frame " << cast_feedback.ack_frame_id; | 287 << " for frame " << cast_feedback.ack_frame_id; |
| 291 if (!is_acked_out_of_order) { | 288 if (!is_acked_out_of_order) { |
| 292 // Cancel resends of acked frames. | 289 // Cancel resends of acked frames. |
| 293 std::vector<uint32> cancel_sending_frames; | 290 std::vector<uint32> cancel_sending_frames; |
| 294 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { | 291 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { |
| 295 latest_acked_frame_id_++; | 292 latest_acked_frame_id_++; |
| 296 cancel_sending_frames.push_back(latest_acked_frame_id_); | 293 cancel_sending_frames.push_back(latest_acked_frame_id_); |
| 297 } | 294 } |
| 298 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); | 295 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
| 299 latest_acked_frame_id_ = cast_feedback.ack_frame_id; | 296 latest_acked_frame_id_ = cast_feedback.ack_frame_id; |
| 300 } | 297 } |
| 301 } | 298 } |
| 302 | 299 |
| 303 bool VideoSender::AreTooManyFramesInFlight() const { | 300 bool VideoSender::ShouldDropNextFrame(base::TimeTicks capture_time) const { |
| 304 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 301 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 305 int frames_in_flight = frames_in_encoder_; | 302 int frames_in_flight = 0; |
| 303 base::TimeDelta duration_in_flight; |
| 306 if (!last_send_time_.is_null()) { | 304 if (!last_send_time_.is_null()) { |
| 307 frames_in_flight += | 305 frames_in_flight = |
| 308 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); | 306 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); |
| 307 if (frames_in_flight > 0) { |
| 308 const uint32 oldest_unacked_frame_id = latest_acked_frame_id_ + 1; |
| 309 duration_in_flight = |
| 310 capture_time - GetRecordedReferenceTime(oldest_unacked_frame_id); |
| 311 } |
| 309 } | 312 } |
| 313 frames_in_flight += frames_in_encoder_; |
| 310 VLOG(2) << frames_in_flight | 314 VLOG(2) << frames_in_flight |
| 311 << " frames in flight; last sent: " << last_sent_frame_id_ | 315 << " frames in flight; last sent: " << last_sent_frame_id_ |
| 312 << " latest acked: " << latest_acked_frame_id_ | 316 << "; latest acked: " << latest_acked_frame_id_ |
| 313 << " frames in encoder: " << frames_in_encoder_; | 317 << "; frames in encoder: " << frames_in_encoder_ |
| 314 return frames_in_flight >= max_unacked_frames_; | 318 << "; duration in flight: " |
| 319 << duration_in_flight.InMicroseconds() << " usec (" |
| 320 << (target_playout_delay_ > base::TimeDelta() ? |
| 321 100 * duration_in_flight / target_playout_delay_ : |
| 322 kint64max) << "%)"; |
| 323 return frames_in_flight >= max_unacked_frames_ || |
| 324 duration_in_flight >= target_playout_delay_; |
| 315 } | 325 } |
| 316 | 326 |
| 317 } // namespace cast | 327 } // namespace cast |
| 318 } // namespace media | 328 } // namespace media |
| OLD | NEW |