| 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 <cmath> | 8 #include <cmath> |
| 9 #include <cstring> | 9 #include <cstring> |
| 10 | 10 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 const PlayoutDelayChangeCB& playout_delay_change_cb) | 88 const PlayoutDelayChangeCB& playout_delay_change_cb) |
| 89 : FrameSender( | 89 : FrameSender( |
| 90 cast_environment, | 90 cast_environment, |
| 91 false, | 91 false, |
| 92 transport_sender, | 92 transport_sender, |
| 93 kVideoFrequency, | 93 kVideoFrequency, |
| 94 video_config.ssrc, | 94 video_config.ssrc, |
| 95 video_config.max_frame_rate, | 95 video_config.max_frame_rate, |
| 96 video_config.min_playout_delay, | 96 video_config.min_playout_delay, |
| 97 video_config.max_playout_delay, | 97 video_config.max_playout_delay, |
| 98 video_config.animated_playout_delay, |
| 98 video_config.use_external_encoder | 99 video_config.use_external_encoder |
| 99 ? NewFixedCongestionControl( | 100 ? NewFixedCongestionControl( |
| 100 (video_config.min_bitrate + video_config.max_bitrate) / 2) | 101 (video_config.min_bitrate + video_config.max_bitrate) / 2) |
| 101 : NewAdaptiveCongestionControl(cast_environment->Clock(), | 102 : NewAdaptiveCongestionControl(cast_environment->Clock(), |
| 102 video_config.max_bitrate, | 103 video_config.max_bitrate, |
| 103 video_config.min_bitrate, | 104 video_config.min_bitrate, |
| 104 video_config.max_frame_rate)), | 105 video_config.max_frame_rate)), |
| 105 frames_in_encoder_(0), | 106 frames_in_encoder_(0), |
| 106 last_bitrate_(0), | 107 last_bitrate_(0), |
| 107 playout_delay_change_cb_(playout_delay_change_cb), | 108 playout_delay_change_cb_(playout_delay_change_cb), |
| 109 interactive_mode_(false), |
| 108 last_reported_deadline_utilization_(-1.0), | 110 last_reported_deadline_utilization_(-1.0), |
| 109 last_reported_lossy_utilization_(-1.0), | 111 last_reported_lossy_utilization_(-1.0), |
| 110 weak_factory_(this) { | 112 weak_factory_(this) { |
| 111 video_encoder_ = VideoEncoder::Create( | 113 video_encoder_ = VideoEncoder::Create( |
| 112 cast_environment_, | 114 cast_environment_, |
| 113 video_config, | 115 video_config, |
| 114 status_change_cb, | 116 status_change_cb, |
| 115 create_vea_cb, | 117 create_vea_cb, |
| 116 create_video_encode_mem_cb); | 118 create_video_encode_mem_cb); |
| 117 if (!video_encoder_) { | 119 if (!video_encoder_) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 LogVideoCaptureTimestamps(cast_environment_.get(), *video_frame, | 156 LogVideoCaptureTimestamps(cast_environment_.get(), *video_frame, |
| 155 rtp_timestamp); | 157 rtp_timestamp); |
| 156 | 158 |
| 157 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 159 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 158 TRACE_EVENT_INSTANT2( | 160 TRACE_EVENT_INSTANT2( |
| 159 "cast_perf_test", "InsertRawVideoFrame", | 161 "cast_perf_test", "InsertRawVideoFrame", |
| 160 TRACE_EVENT_SCOPE_THREAD, | 162 TRACE_EVENT_SCOPE_THREAD, |
| 161 "timestamp", reference_time.ToInternalValue(), | 163 "timestamp", reference_time.ToInternalValue(), |
| 162 "rtp_timestamp", rtp_timestamp); | 164 "rtp_timestamp", rtp_timestamp); |
| 163 | 165 |
| 166 bool interactive_mode; |
| 167 if (video_frame->metadata()->GetBoolean(VideoFrameMetadata::INTERACTIVE_MODE, |
| 168 &interactive_mode)) { |
| 169 if (interactive_mode && !interactive_mode_) { |
| 170 VLOG(1) << "Interactive mode playout time " << min_playout_delay_; |
| 171 playout_delay_change_cb_.Run(min_playout_delay_); |
| 172 } |
| 173 interactive_mode_ = interactive_mode; |
| 174 } |
| 175 |
| 164 // Drop the frame if either its RTP or reference timestamp is not an increase | 176 // Drop the frame if either its RTP or reference timestamp is not an increase |
| 165 // over the last frame's. This protects: 1) the duration calculations that | 177 // over the last frame's. This protects: 1) the duration calculations that |
| 166 // assume timestamps are monotonically non-decreasing, and 2) assumptions made | 178 // assume timestamps are monotonically non-decreasing, and 2) assumptions made |
| 167 // deeper in the implementation where each frame's RTP timestamp needs to be | 179 // deeper in the implementation where each frame's RTP timestamp needs to be |
| 168 // unique. | 180 // unique. |
| 169 if (!last_enqueued_frame_reference_time_.is_null() && | 181 if (!last_enqueued_frame_reference_time_.is_null() && |
| 170 (!IsNewerRtpTimestamp(rtp_timestamp, | 182 (!IsNewerRtpTimestamp(rtp_timestamp, |
| 171 last_enqueued_frame_rtp_timestamp_) || | 183 last_enqueued_frame_rtp_timestamp_) || |
| 172 reference_time <= last_enqueued_frame_reference_time_)) { | 184 reference_time <= last_enqueued_frame_reference_time_)) { |
| 173 VLOG(1) << "Dropping video frame: RTP or reference time did not increase."; | 185 VLOG(1) << "Dropping video frame: RTP or reference time did not increase."; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 185 // OnEncodedVideoFrame(). | 197 // OnEncodedVideoFrame(). |
| 186 const base::TimeDelta duration_added_by_next_frame = frames_in_encoder_ > 0 ? | 198 const base::TimeDelta duration_added_by_next_frame = frames_in_encoder_ > 0 ? |
| 187 reference_time - last_enqueued_frame_reference_time_ : | 199 reference_time - last_enqueued_frame_reference_time_ : |
| 188 base::TimeDelta::FromSecondsD(1.0 / max_frame_rate_); | 200 base::TimeDelta::FromSecondsD(1.0 / max_frame_rate_); |
| 189 | 201 |
| 190 if (ShouldDropNextFrame(duration_added_by_next_frame)) { | 202 if (ShouldDropNextFrame(duration_added_by_next_frame)) { |
| 191 base::TimeDelta new_target_delay = std::min( | 203 base::TimeDelta new_target_delay = std::min( |
| 192 current_round_trip_time_ * kRoundTripsNeeded + | 204 current_round_trip_time_ * kRoundTripsNeeded + |
| 193 base::TimeDelta::FromMilliseconds(kConstantTimeMs), | 205 base::TimeDelta::FromMilliseconds(kConstantTimeMs), |
| 194 max_playout_delay_); | 206 max_playout_delay_); |
| 195 if (new_target_delay > target_playout_delay_) { | 207 // In case of interactive mode, we prefer frame drops over increasing |
| 208 // playout time. |
| 209 if (!interactive_mode_ && new_target_delay > target_playout_delay_) { |
| 210 // In case we detect user is no more in an interactive mode and there is |
| 211 // a need to drop a frame, we ensure the playout delay is at-least the |
| 212 // the starting value for playing animated content. |
| 213 // This is intended to minimize freeze when moving from an interactive |
| 214 // session to watching animating content while being limited by end-to-end |
| 215 // delay. |
| 216 VLOG(1) << "Ensure playout time is at least " << animated_playout_delay_; |
| 217 if (new_target_delay < animated_playout_delay_) |
| 218 new_target_delay = animated_playout_delay_; |
| 196 VLOG(1) << "New target delay: " << new_target_delay.InMilliseconds(); | 219 VLOG(1) << "New target delay: " << new_target_delay.InMilliseconds(); |
| 197 playout_delay_change_cb_.Run(new_target_delay); | 220 playout_delay_change_cb_.Run(new_target_delay); |
| 198 } | 221 } |
| 199 | 222 |
| 200 // Some encoder implementations have a frame window for analysis. Since we | 223 // Some encoder implementations have a frame window for analysis. Since we |
| 201 // are dropping this frame, unless we instruct the encoder to flush all the | 224 // are dropping this frame, unless we instruct the encoder to flush all the |
| 202 // frames that have been enqueued for encoding, frames_in_encoder_ and | 225 // frames that have been enqueued for encoding, frames_in_encoder_ and |
| 203 // last_enqueued_frame_reference_time_ will never be updated and we will | 226 // last_enqueued_frame_reference_time_ will never be updated and we will |
| 204 // drop every subsequent frame for the rest of the session. | 227 // drop every subsequent frame for the rest of the session. |
| 205 video_encoder_->EmitFrames(); | 228 video_encoder_->EmitFrames(); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 media::VideoFrameMetadata::RESOURCE_UTILIZATION, | 379 media::VideoFrameMetadata::RESOURCE_UTILIZATION, |
| 357 encoded_frame->dependency == EncodedFrame::KEY ? | 380 encoded_frame->dependency == EncodedFrame::KEY ? |
| 358 std::min(1.0, attenuated_utilization) : attenuated_utilization); | 381 std::min(1.0, attenuated_utilization) : attenuated_utilization); |
| 359 } | 382 } |
| 360 | 383 |
| 361 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); | 384 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); |
| 362 } | 385 } |
| 363 | 386 |
| 364 } // namespace cast | 387 } // namespace cast |
| 365 } // namespace media | 388 } // namespace media |
| OLD | NEW |